当用C中的指针定义时,为什么我们使用`const`作为字符串?

ami*_*ali 5 c arrays string pointers const

我从一位C开发人员那里听说,为了使用指针定义数组,我们编写
int *const a;
因为数组具有变量值而是常量指针.但对于字符串,我们写
const char *s;.

我不明白为什么.它是否正确?字符串在C中是否真的具有常量值和变量指针?

Tim*_*all 6

考虑以下:

char* a;
char* const b = "Hello"
const char* c;
const char* const d = "world";
Run Code Online (Sandbox Code Playgroud)

a只是指向一个字符。这可能是字符串的第一个字符,也可能是单个字节。可以通过写入*a='Z'a[0]='q'传递a给带char*参数的函数来修改该字符。指针本身也可以修改为指向其他一些字符,例如a=b;a="foo";。这是最灵活的形式,也是最不安全的形式,因为您可以用它做任何事情。

b是一个指向字符的常量指针。在这种情况下,它指向一个字符数组。这些字符可以被修改,例如b[1]='a';或者*b=0;b它本身是不变的,这意味着它永远不能指向内存的不同部分。当您分配了一个缓冲区或数组,其内容要修改但不能移动时,可以使用这种形式,因为它是由操作系统分配的。

c指向一个常量字符。您可以更改它所指向的 (c="foo";c=b;) 但您不能使用此指针来更改它所指向的字符——即使它指向的是非常量缓冲区 b。这种形式通常用于处理预先生成的字符串。您可以使用此变量来存储您找到的字符串,并传递它们的地址,只要您不更改字符串本身。

d是指向常量字符的常量指针。您不能更改它所指向的字符,也不能将指针本身指向不同的内存位置。您所能做的就是读取字符串或单个字符(char e=d[4];puts(d);)。这种形式主要用于传递引用字符串,例如命名真实对象时。


Lun*_*din 4

int *const a;在大多数用例中,诸如此类的代码都是无意义的。制作指针的主要用途const是当您有基于指针的查找表时。或者当您希望将指针存储在嵌入式系统上的只读存储器中时。

一些困惑的程序员喜欢编写这样的代码void func (int* const ptr),但在我看来,这只是混淆,因为ptr无论如何都是原始指针的副本,并且调用者不在乎该函数在内部对其本地副本执行什么操作。

不要与const 正确性混淆,这意味着指向只读数据的指针应声明为const int* ptr. 这被广泛认为是良好的编程实践,并且它是规范的 C,因为大多数 C 标准都使用 C 标准库的 const 正确性。

具体而言,对于指向字符串文字的指针(例如"hello"),应该声明它们const char* ptr = "hello";,因为修改字符串文字会调用未定义的行为。这意味着修改它是一个错误,可能会导致程序崩溃。这是 C 中的一个已知缺陷 - 字符串文字本身的类型,即使我们不允许写入它,也是char[]. 这是有历史原因的。然而,在 C++ 中,他们修复了从 C 继承的语言缺陷,因此所有字符串文字都在const char[]C++ 中。