C 为什么我有时可以修改常量对象,有时不能?
我有两段代码试图修改只读位置的值。其中一个正在抛出一个错误 1stcode.cC 为什么我有时可以修改常量对象,有时不能?,c,pointers,constants,C,Pointers,Constants,我有两段代码试图修改只读位置的值。其中一个正在抛出一个错误 1stcode.c void main() { int const k=9; int *p=&k; *p=10; printf("%d",k); } 2ndcode.c void main() { int const * p=5; printf("%d",++(*p)); } 此处1stcode.c允许我简单地修改只读内存位置,但2ndcode.c会抛出一个错误: 错误:只读位置“*
void main()
{
int const k=9;
int *p=&k;
*p=10;
printf("%d",k);
}
2ndcode.c
void main()
{
int const * p=5;
printf("%d",++(*p));
}
此处1stcode.c
允许我简单地修改只读内存位置,但2ndcode.c
会抛出一个错误:
错误:只读位置“*p”的增量
为什么这两个位置都是只读的呢?如果将编译器警告级别调高,第一个示例也不会编译
还请注意,在第二个示例中,您声明了一个指向地址5的指针,它不会做任何有用的事情。如果您将编译器警告级别调高,第一个示例也不会编译
另外请注意,在第二个示例中,您声明了一个指向地址5的指针,这不会有任何用处。第一个代码也不正确
您可以使用指向
int
的指针指向定义为const int
的对象,并修改该对象。这是一个格式错误的C程序,但是编译器没有检测到错误(嗯,它可能会给你一个警告)。因此,可能会出现bug,尤其是在启用优化的情况下(编译器可以假定值没有更改)
代码仍然可以编译,因为C是弱类型的,并且允许在不兼容的类型之间进行隐式转换(在本例中,从const int*
到int*
)
(注意C++中的不同,如果你尝试过这种转换,会给你一个编译错误)。
< P>第一个代码也不正确。你用一个指向
int
的指针指向一个定义为const int
的对象并修改它。这是一个格式错误的C程序,但编译器没有检测到错误(它可能会给你一个警告)。你可能会因此而出现错误,特别是当你打开优化时(编译器可以假定该值没有更改)
代码仍然可以编译,因为C是弱类型的,并且允许在不兼容的类型之间进行隐式转换(在本例中,从const int*
到int*
)
(注意C++中的不同,如果你尝试过这种转换,会给你编译错误。)
< P>:: 6.7.3类型限定符…
5如果试图通过使用修改由常量限定类型定义的对象 对于具有非常量限定类型的左值,行为未定义。如果尝试 通过使用左值来引用使用volatile限定类型定义的对象 对于非易失性限定类型,行为未定义。115) 您试图通过
*p
(具有非常量限定类型的左值)修改k
(使用常量限定类型定义的对象)的内容,因此行为未定义,其中“未定义”简单地说,标准不要求编译器执行任何特定操作。在这种情况下,编译器翻译代码的方式使操作“正常”,但您不应依赖于该行为的可重复性。更智能的编译器(或更严格的警告设置)可能会发出诊断并在此时停止翻译。也可能不会。在一般情况下,这个问题是一个需要检测的问题,这就是为什么我怀疑这个行为只是没有定义
在第二种情况下,您已将p
声明为指向const int
的指针;不允许修改*p
,而+(*p)
尝试这样做。来自:
6.7.3类型限定符…
5如果试图通过使用修改由常量限定类型定义的对象 对于具有非常量限定类型的左值,行为未定义。如果尝试 通过使用左值来引用使用volatile限定类型定义的对象 对于非易失性限定类型,行为未定义。115) 您试图通过
*p
(具有非常量限定类型的左值)修改k
(使用常量限定类型定义的对象)的内容,因此行为未定义,其中“未定义”简单地说,标准不要求编译器执行任何特定操作。在这种情况下,编译器翻译代码的方式使操作“正常”,但您不应依赖于该行为的可重复性。更智能的编译器(或更严格的警告设置)可能会发出诊断并在此时停止翻译。也可能不会。在一般情况下,这个问题是一个需要检测的问题,这就是为什么我怀疑这个行为只是没有定义
在第二种情况下,您已将
p
声明为指向常量int
的指针;不允许修改*p
,这是+(*p)
尝试这样做。我没有投反对票,但我知道有人投反对票。在你的第一段代码中,你将常量
限定变量的地址强制转换为一个假装不是的变量。然后你问我们为什么编译器会接受这一点?我没有投反对票,但我知道有人投反对票。在你的第一段代码中,你将限定变量的地址强制转换为cOnS/<代码>合格的变量,假装它不是。然后你问我们为什么编译器接受这个?“这是一个不合格的C程序”——除非我的定义混淆了,它在C.中没有形成错误,它只是不明确的行为,它将在C++中形成不良。“这是一个不合格的C程序”除非我的定义混淆了,否则它在C.没有形成错误,它只是有不明确的行为,而且它在C++中是不正确的。标准有什么说法?是允许转换还是实现定义的行为?或者是别的什么?@帕门德:我不确定,它没有在第6.3节中描述。(实际上是隐式变换的列表)