常量字符 [] 和常量字符*之间的区别

Difference Between const char[] and const char*

本文关键字:常量 字符 区别 之间      更新时间:2023-10-16

所以这篇文章正在讨论声明字符串文字的使用,就像它以声明结尾const char* foo = "foo"

const char *foo = "foo";
几乎从来都不是你想要的。相反,您希望使用以下形式之一:

  • 对于要导出的字符串:
    const char foo[] = "foo";
  • 对于要在同一源文件中使用的字符串:
    static const char foo[] = "foo";
  • 对于要跨同一库的多个源文件使用的字符串:
    __attribute__((visibility("hidden"))) const char foo[] = "foo";

我的理解是,const char* const foo = "foo"等同于const char foo[] = "foo",因为我们谈论的是一个 C 字符串指针,它永远不能更改为指向其他任何东西,而const char* foo = "foo"可以用来指向任何其他 C 字符串。

这是一个准确的概要吗?始终使用const char* constconst char[]

让我们在这里变得迂腐。

char const * const p_foo = "foo";

上面定义了一个指向 {常量} 字符文字"foo"的{常量}指针。指针指向字符文本的第一个字符。

const char bar[] = "bar";
  • 上面定义了一个字符数组。
  • 字符数组是*只读的"。
  • 字符数组是文本文字"bar"的长度加上 NUL 终止符(4 个字符(。
  • 文本
  • 文本的内容将复制到数组中。(的 编译器可能会优化此步骤(。

从根本上说,指向文本第一个字符的指针和数组之间存在差异。

指针指向单个字符。递增指针可能不会指向有效的实体(因为它不是数组,而是指向单个基准面的指针(。 有一个基本假设,即指针可以递增到下一个字符。

对于数组,您知道内存中顺序有多个字符(前提是数组的长度为 2 或更大(。 您不知道序列(集合(中是否存在终止 NUL。 您可以假设这一点,但字符数组并不能保证这一点。

用法
使用数组声明,文本的长度在编译时是已知的。

使用指针声明时,需要使用strlen来确定运行时文本的长度。 运行时代码不知道目标数据字符串的长度;只能保证长度为 1。

有时,使用staticconst可以帮助编译器进行优化。
例如:

static const char moo[] = "moo";

允许编译器直接访问文本,而无需创建数组变量并将文本复制到变量中。

在接收指向字符的指针的函数中,无法保证指针指向有效位置(指针的内容可能无效(。

每个声明都有其优点和副作用。
选择权在你。

正如托马斯·马修斯的回答所说,const char*const char* const都是指针,const char[]是数组。

但正如这里所说的那样,使用指针有 3 个问题:

  1. 需要用于指针存储的内存
  2. 指针产生的间接寻址是必需的
  3. 指针
  4. 需要单独存储数组或数组大小的结束指针

最终如链接中所示:

简单的答案是,在声明变量时,您应该首选const char[]

我同意数组在计算时会衰减为指针,但有一些功能仅适用于数组。例如,当您声明一个数组时,您有关于数组大小的其他信息。

此外,对于固定数组的情况,内存是专门为 foo 分配的。因此,您可以像往常一样更改数组的内容,并且数组将被销毁,在超出范围(典型的局部变量(时解除分配内存。

当您将其定义为指针时,编译器会将 foo 放入只读内存中,然后指向它(通常(。请注意,这就是为什么大多数情况下常量字符串被定义为 char*,甚至编译器也会在将其设置为非常量指针时发出警告。

#include <iostream>
int main()
{
char* a = "foo";
return 0;
} 

此代码会向您抛出如下警告:

ISO C++禁止将字符串常量转换为"char*" [-Wwrite-strings] 字符* a = "foo";

您尝试对字符串进行的任何更改通常都会导致分段错误。