0

我对 ANSI 规范所说的关于更改声明的变量const可以通过其地址合法修改的内容感到困惑。不幸的是,我无权访问 C90 规范,但得到了冲突的指针:

  1. 关键字 const 不会将变量变成常量!带有 const 限定符的符号仅表示该符号不能用于赋值。这使得值只能通过该符号读取;它不会阻止通过程序内部(甚至外部)的某些其他方式修改值。它仅对限定指针参数非常有用,以指示此函数不会更改参数指向的数据,但其他函数可能会。(专家 C 编程:Deep C Secrets:Peter van der Linden)

  2. 如果尝试通过使用具有非 const 限定类型的左值来修改使用 const 限定类型定义的对象,则行为未定义。如果尝试通过使用具有非 volatile 限定类型的左值来引用使用 volatile 限定类型定义的对象,则行为未定义。( http://flash-gordon.me.uk/ansi.c.txt )

我在 C99 规范 (n1256.pdf) 中看到了后者。

谁能澄清一下以上两种观点中哪一种是正确的?

const编辑:Expect C Programming 实际上给出了一个示例来演示使用指针更改变量的能力。

4

6 回答 6

2

不知道 C90,但 C11 包含这个子句,我想它从第一天就已经存在(C11,6.7.3/6):

如果尝试通过使用具有非 const 限定类型的左值来修改使用 const 限定类型定义的对象,则行为未定义。

对于volatile- 限定的对象也是如此。

于 2013-09-12T08:48:00.243 回答
2

It's similar in C90(C89) as C99.

C89 §3.5.3 Type qualifiers

If an attempt is made to modify an object defined with a const-qualified type through use of an lvalue with non-const-qualified type, the behavior is undefined. If an attempt is made to refer to an object defined with a volatile-qualified type through use of an lvalue with non-volatile-qualified type, the behavior is undefined.

Undefined behavior doesn't mean that C prohibits it at all, just the behavior is, well, not defined. So actually the two of your statements are both true.

于 2013-09-12T08:53:12.933 回答
0

如果您尝试修改 const 变量,则行为未定义是合乎逻辑的。考虑将代码 + 常量放在 ROM 中的嵌入式平台。在这种情况下,根本不可能更改该值,因为它会永远被烧毁。就好像一切都驻留在 RAM 中一样,它很可能是可变的。这就是为什么标准在这种情况下说“未定义的行为” - 行为必须依赖于平台和编译器。

声明 1 和 2 并不是真正相互排斥的。

于 2013-09-12T08:49:08.087 回答
0

什么声明,例如:

T const *p; //p has type “pointer to const T

方法?
程序可以使用表达式 p 更改p指定的指针对象的值,但不能使用表达式*p更改*p可能指定的任何对象的值。如果程序有另一个非限定类型的表达式e指定一个对象,该对象*p也指定,程序仍然可以e用来更改该对象。因此,程序可能能够直接从const-qualified表达式下更改对象。

于 2013-09-12T08:50:46.903 回答
0

使用指针可以更改const变量,因为它只是一个内存位置,因此它肯定会接受指针方法所做的更改。

但是由于这个变量是这样定义的,const所以它的值的变化会引发未定义的行为

于 2013-09-12T08:51:17.890 回答
0

是什么让你觉得这两种说法是相互排斥的?

const只是一个类型限定符,没什么神奇的。

内存仍然可以通过外部方式更改,或者通过绕过编译器识别类型限制的能力。第二个陈述只是说尝试这样做会产生不确定的结果。它可能会也可能不会改变值。

在我看来,这两种说法都没有任何矛盾之处。

于 2013-09-12T09:08:49.347 回答