为什么我有时可以修改const对象,有时不修改?

时间:2012-02-23 12:05:41

标签: c pointers const

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

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

  

error: increment of read-only location '*p'

为什么两个位置都是只读的呢?

3 个答案:

答案 0 :(得分:4)

如果您将编译器警告级别提高,第一个示例也将无法编译。


另请注意,在第二个示例中,您将声明一个指向地址5的指针,这不会做任何有用的事情。

答案 1 :(得分:2)

第一个代码也不正确。

指向int的指针指向定义为const int的对象并修改它。这是一个格式错误的C程序,但编译器没有检测到错误(好吧,它可能会给你一个警告)。您可能会因此而出现错误,特别是如果您启用优化(编译器可以假设该值未更改)。

代码仍在编译,因为C是弱类型的,允许在不兼容的类型之间进行隐式转换(在这种情况下,从const int*int*

(请注意,这在C ++中是不同的,这是更严格的,如果您尝试进行此类转换,则会出现编译错误。)

答案 2 :(得分:0)

来自online C99 standard

6.7.3类型限定词
...
5如果尝试通过使用修改使用const限定类型定义的对象 如果是非const限定类型的左值,则行为未定义。如果是尝试 通过使用左值来引用用volatile限定类型定义的对象 对于非易失性限定类型,行为未定义。 115)

您正在尝试通过k(具有非const限定类型的左值)修改*p(使用const限定类型定义的对象)的内容,因此行为未定义,其中“undefined”仅表示标准不要求编译器特别做任何事情。在这种情况下,编译器以操作“工作”的方式转换代码,但您不应该依赖该行为是可重复的。更智能的编译器(或更严格的警告设置)可能会在此时发出诊断并停止翻译。或者它可能不会。这个问题是在一般情况下检测的错误,这就是为什么我怀疑行为只是未定义的原因。

在第二种情况下,您已将p声明为指向const int的指针;您不能修改*p++(*p)尝试执行此操作。