为了定义带有指针的数组,我们编写
int *const a;
因为数组具有变量值但具有常量指针。但是对于字符串,我们写
const char *s;
。
我不明白为什么。它是否正确?字符串在C中真的有常量值和变量指针吗?
答案 0 :(得分:4)
在大多数用例中,诸如int *const a;
之类的代码都是无用的。制作指针const
的主要用途是当您有一个基于指针的查找表时。或者,当您希望将指针存储在嵌入式系统的只读存储器中时。
一些困惑的程序员喜欢编写void func (int* const ptr)
之类的代码,但是在我看来,这只是一种混淆,因为ptr
无论如何都是原始指针的副本,并且调用者不在乎什么该函数在内部使用其本地副本。
请勿与常量正确性混淆,这意味着指向只读数据的指针应声明为const int* ptr
。这被广泛认为是良好的编程习惯,并且是规范的C,因为大多数C标准都对C标准库使用const正确性。
对于指向字符串文字的指针(例如"hello"
),由于修改字符串文字会调用未定义的行为,因此应将其声明为const char* ptr = "hello";
。这意味着修改它是一个错误,并且可能导致程序崩溃。这是C语言中的一个已知缺陷-字符串文字本身的类型为char[]
,即使我们不允许对其进行写入。这是出于历史原因。但是,在C ++中,他们修复了从C继承的语言缺陷,因此所有字符串文字在C ++中都是const char[]
。
答案 1 :(得分:2)
请考虑以下内容:
char* a;
char* const b = "Hello"
const char* c;
const char* const d = "world";
a
只是指向一个字符。那可能是字符串的第一个字符或单个字节。可以通过写*a='Z'
或a[0]='q'
或将a
传递给带有char*
参数的函数来修改该字符。指针本身也可以修改为指向其他一些字符,例如a=b;
或a="foo";
。这是最灵活,最不安全的表单,因为您可以使用它进行任何操作。
b
是指向字符的常量指针。在这种情况下,它指向一个字符数组。可以修改这些字符,例如b[1]='a';
或*b=0;
,但b
本身是常量,这意味着它永远无法指向内存的不同部分。当您分配了要修改其内容但由于操作系统分配的内容而无法移动的缓冲区或数组时,可以使用此格式。
c
指向常量字符。您可以更改其指向的内容(c="foo";
或c=b;
,但是您不能使用此指针来更改其指向的字符-,即使它指向的是非恒定缓冲区< / em> b
。处理预生成的字符串时,通常使用这种形式。您可以使用此变量存储找到的字符串,并在其周围传递地址,只要您自己不更改字符串即可。
d
是指向常量字符的常量指针。您不能更改其指向的字符,也不能将指针本身指向其他存储位置。您所要做的就是读取字符串或单个字符(char e=d[4];
或puts(d);
)。这种形式主要用于传递参考字符串时,例如在命名真实对象时。
答案 2 :(得分:1)
使用此语句时
char *str = "Stack Overflow";
这意味着str
指向字符串"Stack Overflow"
,该字符串存储在代码存储器中,不允许用户对其进行修改。因此,对于此语句,在const
之前写入char *str
不会产生任何效果,因为字符串已经是常量。
但是当您指向数组的基地址(例如
)时,const
扮演着重要的角色
char arr[20];
strcpy(arr,"Stack Overflow");
const char *str = arr;
使用const
意味着您无法通过指针arr
修改str
中的字符串。
使用时
char * const ptr;
这意味着ptr
不能指向其初始地址以外的其他地址。当您不打算在整个程序中更改指针地址时使用它,例如指向在嵌入式系统中查找表。