看看这个节目:
#include <iostream>
using namespace std;
int main()
{
const int x = 0;
int *p;
p=(int*)&x;
(*p)++;
cout<<x<<endl;
cout<<*p;
}
如上所述,我将x
声明为const int
,并使用强制转换,一个名为p
的非常量指针指向它。在我的程序正文中间,我使用x
将(*p)++
的值增加了一个(如何可能,x
被定义为const?)
现在,当我打印*p
和x
时,它们会返回不同的值,而*p
应该指向x
的地址:
ap1019@sharifvm:~$ ./a.out
0
1
为什么?
答案 0 :(得分:6)
恒定删除后变量的变化会导致未定义的行为,在某些情况下,它只会起作用,就好像它不会是const一样,在某些情况下它会导致内存冲突错误,在某些情况下,它会把你的电脑变成兔子,试图杀死你......
关于行为的一些背景知识。想象一下你是一个编译器。您遇到变量:
const int blah = 3;
然后您会遇到以下操作:
int foo = 4 + blah;
因为你是聪明的编译器而且你知道blah是常量 - 因此它不会改变,而不是从blah中读取值,你可以交换值来获取内存中的blah存储位置读取它只需添加3到4并将其分配给foo。
婴儿你可能会立即分配7,因为每次运行程序时添加都是没有意义的。
让我们现在进入抛弃const部分。
一些非常偷偷摸摸的程序员正在做以下事情:
int * blah_pointer = (int *) & blah;
然后他通过执行此操作来增加blah值:
(*blah_pointer)++;
会发生什么 - 如果变量不在受保护的存储器中(不是只读),程序将只增加存储在存储器中的变量的值。
现在,当您读取存储在指针中的值时,您将获得增加的值!
好的,但是如果你正在阅读我听到的问题,为什么会有一个旧的,不变的值:
std::cout << blah;
它就在那里,因为编译器试图变得聪明,而不是实际从blah读取值,它只是将它交换为常量值为blah,所以不是读它而是实际将它交换到std :: cout &LT;&LT; 3。
未定义的部分正在改变常数值 - 您无法知道该值是否会存储在受保护或未受保护的区域中,因此您无法说明会发生什么。
如果您希望编译器在每次遇到它时实际检查该值,只需更改定义:
const int blah = 3;
到
const volatile int blah = 3;
它将告诉编译器以下内容,即使我正在编写的程序不允许更改blah值,也可能在程序执行期间更改,因此不要尝试优化对内存的访问权限每次使用该值时都读取它。
我希望这更清楚。
答案 1 :(得分:3)
我认为,在编译步骤中,编译器会将所有常量变量替换为其值(类似#define
),这是GNU GCC编译器优化代码的方式。登记/>
我对此并不是百分之百确定,但在学习C / C ++语法时我遇到了同样的问题,而且这是我在解体后做出的结论(转换二进制文件)可执行程序到汇编代码)我的程序。
无论如何,只是尝试反汇编你的输出,看看到底发生了什么。