来自this article。
将变量声明为
register
和const
的另一种用途是禁止对该变量进行任何非局部更改,即使是通过获取其地址然后强制转换指针也是如此。即使您认为自己永远也不会这样做,一旦将指针((带有const属性)]传递给其他函数,您将永远无法确定这可能是恶意的并在您的脚下更改变量。
我不明白我们如何通过指针修改const
变量的值。这不是未定义的行为吗?
const int a = 81;
int *p = (int *)&a;
*p = 42; /* not allowed */
作者的观点是,使用register
存储类声明变量会阻止您获取其地址,因此无法将其传递给可能通过丢弃const
来更改其值的函数。
void bad_func(const int *p) {
int *q = (int *) p; // casting away const
*q = 42; // potential undefined behaviour
}
void my_func() {
int i = 4;
const int j = 5;
register const int k = 6;
bad_func(&i); // ugly but allowed
bad_func(&j); // oops - undefined behaviour invoked
bad_func(&k); // constraint violation; diagnostic required
}
通过将潜在的UB更改为违反约束条件,就需要进行诊断,并且(必须)对错误进行诊断。在编译时]:
5.1.1.3诊断
1-如果预处理翻译单元或翻译单元,符合标准的实现应产生至少一个诊断消息[...]包含违反任何语法规则或约束的行为,即使该行为也是显式的指定为未定义或实现定义。
6.5.3.2地址和间接操作符约束条件
1-一元
&
运算符的操作数应为一个左值,该左值指定一个对象,该对象是未用register
存储类说明符声明。请注意,
register
数组对象上的数组到指针的衰减是未定义的行为,不需要诊断(6.3.2.1:3)。
还请注意,使用C ++中允许的register
左值is
register
只是一个优化提示(并且不推荐使用)。我们可以修改
const
变量的值吗?
您的代码已编译,但是具有未定义的行为。
该代码片段确实调用了未定义的行为。
我认为作者也在谈论此案,这是对const
的误解: