似乎const on array将导致用于将数组标记存储在内存中的内存只读。但是为什么const on int不会做同样的事情呢?
代码在这里:
int main(int argc, const char * argv[])
{
const int vv = 10 ;
int * p = (int *)&vv ;
*p = 5 ; // work well
const int aa[3] = {11, 12, 13} ;
int * pp = (int *)&aa[1] ;
*pp = 100 ; // EXC_BAD_ACCESS
return 0;
}
答案 0 :(得分:3)
如第7.1.6.1 / 4节所述,第一个和第二个都导致未定义的行为:
除了可以修改声明为mutable(7.1.1)的任何类成员之外,任何在其生命周期内修改const对象的尝试(3.8)都会导致未定义的行为。
事实上,这是其中一种情况,其中C ++风格的演员表(如static_cast
),const_cast
,would have warned you除外。
在C标准中,相同的参考文献在§6.7.3/ 5中进行:
如果尝试通过使用具有非const限定类型的左值来修改使用const限定类型定义的对象,则行为未定义。
答案 1 :(得分:2)
任何修改const
数据的尝试都会导致未定义的行为(UB)。这意味着您的代码似乎“运行良好”,但不能依赖它。
你的例子都是UB。
答案 2 :(得分:2)
如果您在第二次访问时获得了错误的访问权限,则意味着您的编译器不会将初始化程序列表复制到aa
,但是aa
指向进程的const数据部分(例如,字符串文字的位置)存储)。
正如其他人所指出的那样,更改const会产生未定义的行为。在Visual Studio中,您的代码不会产生任何错误。
当出现对同一个const对象(或C中的数组)的多个引用时,问题浮出水面。更改一个将改变所有这些并且仅在优化的构建中。这种错误很难跟踪。
答案 3 :(得分:1)
如果尝试通过使用具有非const限定类型的左值来修改使用const限定类型定义的对象,则行为未定义。如果尝试通过使用具有非volatile限定类型的左值来引用使用volatile限定类型定义的对象,则行为是未定义的。
所以我猜这对C来说已经足够清楚了,不是吗?
答案 4 :(得分:0)
您的第一部分代码非常正确。您正在使用其引用修改存储在位置的值。这是定义的行为。编译器检查此变量不在表达式的左侧。
使用以下内容使其指向的值保持不变。
const int * p = (int *)&vv