普通int
是可变的。一个实体(不仅声称在某个时候是,而且“确实是”)const
在理论上是不可变的,如果硬件和软件合作,通常也是实际上不可变的。
使用限定符定义变量const
使其“真正”为 const:
const int c3 = 3;
void f(void) {
const int c4 = 4;
...
}
使用“棘手”的代码(抛弃 const-ness),您可以说服系统将新值写入或尝试写入c3
和/或c4
:
void f(void) {
const int c4 = 4;
int *p;
p = (int *)&c3;
*p = 99;
printf("c3 is now %d\n", c3);
}
如果您打电话给f()
您,在某些系统上,您可能会发现 c3 更改并变为 99。在其他系统上,您可能会收到“分段错误”或其他运行时错误。
将引用更改为使用c4
,同样的事情也会发生——尽管在实践中,很少有系统会产生运行时错误。但是,您可能会完全观察到其他事情:c4 is now 99
您可能会得到c4 is now 4
.
最后一种情况可能会发生,因为允许编译器假设,在将c4
a设为const int
4 后,您(程序员)从未更改过它。那*p = 99
一定没有改变它(即使它改变了),所以printf
可以用另一个只打印 4 的调用来替换对的调用。
对 的引用通常也是如此c3
:编译器可以假设由于您承诺永远不会更改它,因此您实际上从未更改过它。这可能会产生令人惊讶的结果,例如:p == &c3
为真、c3
为 3 和*p
为 99。但很可能会出现运行时错误,因为大多数现代编译器和操作系统都会合作c3
进入只读区域。
当字符串文字产生数组时(大多数情况下),C 有一个怪癖。这些数组不是const
- 限定的,但组成数组的字符无论如何都是只读的(至少在原则上,与 一样const int c3 = 3;
)。就像c3
,大多数现代系统都设法使它们“真正只读”。
(字符串文字在用作类型对象的初始值设定项时不会生成数组array of char
。比较:
char *ronly = "this string is read only";
char rwarray[] = "this string is read/write";
这ronly
是一个指针,而不是数组,因此字符串字面量生成一个数组并ronly
指向该数组的第一个字符。底层数组是只读的,即使它的类型是char [25]
. Butrwarray
是一个数组,而不是一个指针,所以字符串字面量填充它——并将它的大小设置为 26——它是可变的。您必须编写const char roarray[] = ...
以使其不可变。[有些人喜欢拼写 type char const []
, const 跟在 data-type 之后。这些意思是一样的。])