Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/62.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 为什么我有时可以修改常量对象,有时不能?_C_Pointers_Constants - Fatal编程技术网

C 为什么我有时可以修改常量对象,有时不能?

C 为什么我有时可以修改常量对象,有时不能?,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会抛出一个错误: 错误:只读位置“*

我有两段代码试图修改只读位置的值。其中一个正在抛出一个错误

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
会抛出一个错误:

错误:只读位置“*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节中描述。(实际上是隐式变换的列表)