我们可以修改const变量的值吗?
从这篇文章 。
将变量声明为
register
和const
另一个用途是禁止该变量的任何非局部更改,即使通过获取其地址然后转换指针也是如此。 即使你认为自己永远不会这样做,一旦你将一个指针(即使有一个const属性)传递给其他函数,你也永远无法确定这可能是恶意的并且改变你脚下的变量。
我不明白我们如何通过指针修改const
变量的值。 是不是未定义的行为?
const int a = 81; int *p = (int *)&a; *p = 42; /* not allowed */
作者的观点是,使用register
存储类声明变量会阻止您获取其地址,因此无法将其传递给可能通过转换const
来更改其值的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更改为约束违规,需要进行诊断并在编译时诊断错误(需要):
C11
5.1.1.3诊断
1 – 如果预处理转换单元或转换单元包含违反任何语法规则或约束的情况,则符合要求的实现应生成至少一条诊断消息,即使该行为也明确指定为未定义或实现定义。
6.5.3.2地址和间接运营商
约束
1 – 一元
&
运算符的操作数应为[…]一个左值,它指定一个没有用register
存储类说明符声明的对象。
请注意, register
数组对象上的数组到指针衰减是未定义的行为,不需要诊断(6.3.2.1:3)。
另请注意,在C ++中允许使用register
左值的地址,其中register
只是一个优化提示(并且在此处不推荐使用)。
我们可以修改
const
变量的值吗?
是的,您可以通过各种方式修改const
变量:指针hackery,强制转换等…
请继续阅读下一个Q !!
是修改
const
变量值的有效代码吗?
没有! 给你的是未定义的行为 。
技术上,您的代码示例具有未定义的行为 。
一旦修改const
,程序就不会遵循c标准,因此可能会给出任何结果。
请注意,未定义的行为并不意味着编译器需要将违规报告为诊断。 在这种情况下,您的代码使用指针hackery来修改const
并且不需要编译器来为其提供诊断。
C99标准3.4.3说:
未定义的行为:使用不可移植或错误的程序结构或错误数据时的行为,本国际标准不对此要求。
注意可能的未定义行为包括完全忽略具有不可预测结果的情况,在转换或程序执行期间以环境特征(有或没有发出诊断消息)的文档方式执行,终止转换或执行(使用发出诊断信息)。
您的代码编译,但它有未定义的行为。
作者的观点是使用const
和 register
以便代码不再编译:
const int a = 81; int *p = (int *)&a; /* no compile error */ *p = 42; /* UB */ register const int b = 81; int *q = (int *)&b; /* does not compile */
代码片段确实调用了未定义的行为。
我不太确定作者的观点是什么:为了不让“外来代码”改变变量的值,你使它成为const
以便…而是调用UB? 这怎么样? 坦率地说,没有意义。
我认为作者也在谈论这个案例,这是对const
一种误解:
int a = 1; int* const a_ptr = (int* const)&a; //cast not relevant int function(int* const p){ int* malicious = (int*)p; *malicious = 2; }
变量本身不是常量,而是指针。 恶意代码可以转换为常规指针,并合法修改下面的变量。