与const和指针相关的问题

Jat*_*tin 1 c++ pointers integer const

我写了2个程序.请仔细阅读这两个程序并帮助我理解为什么变量'i'和'*ptr'给出不同的值.

//Program I:
//Assumption: Address of i = 100, address of ptr = 500

int i = 5;
int *ptr = (int *) &i;

*ptr = 99;

cout<<i; // 99
cout<<&i;// 100
cout<<ptr; // 100
cout<<*ptr; // 99
cout<<&ptr; // 500
//END_Program_I===============

//Program II:
//Assumption: Address of i = 100, address of ptr = 500
const int i = 5;
int *ptr = (int *) &i;

*ptr = 99;

cout<<i; // 5
cout<<&i;// 100
cout<<ptr; // 100
cout<<*ptr; // 99
cout<<&ptr; // 500
//END_PROGRAM_II===============
Run Code Online (Sandbox Code Playgroud)

困惑是:为什么变量我仍然是5,即使*ptr == 99?

Mys*_*ial 6

在以下三行中,您正在修改常量:

const int i = 5;
int *ptr = (int *) &i;

*ptr = 99;
Run Code Online (Sandbox Code Playgroud)

这是未定义的行为.任何事情都可能发生.所以不要这样做.


至于在这种特殊情况下发生的事情:

因为iconst,编译器假定它不会改变.因此,它只是简单地将其5用于每个使用它的地方.这就是打印输出i显示原始值的原因5.


Emi*_*lia 5

所有答案都可能会讨论"未定义的行为",因为您正在尝试修改常量的逻辑无意义.

虽然这在技术上是完美的,但是让我给你一些关于为什么会发生这种情况的提示(关于"如何",请参阅Mysticial回答).

之所以发生这种情况,是因为C++ 在设计上是一种" 不完美指定的语言 "."不完美"包含许多贯穿语言规范的"未定义行为".

事实上,语言设计师故意选择 - 在某些情况下 - 而不是说"如果你这样做,会给你那个",(可能是:你有这个代码,或者你有这个错误),他更喜欢说"我们不要定义会发生什么".

这使编译器制造商可以自由决定做什么.并且由于有许多编译器在许多平台上工作,可能是一个最佳解决方案,不一定是另一个的最佳解决方案(可能依赖于具有不同指令集的机器),因此您(作为程序员)留下在戏剧性的情况下,你永远不会知道会发生什么,即使你测试它,你也不能相信测试的结果,因为在另一种情况下(用不同的编译器编译相同的代码或只是不同的版本) ,或者对于不同的平台,它会有所不同.

这里的"坏"事情是编译器应该在遇到未定义的行为时发出警告(强制const应该被警告为潜在的错误,特别是如果编译器执行const内联otimizations,因为如果是const,它是无意义的如果你指定了正确的标志(可能是-W4或-wall或-pedantic或类似的,取决于你的编译器),可以允许更改).

特别是这条线

int *ptr = (int *) &i;
Run Code Online (Sandbox Code Playgroud)

应发出如下警告: warning: removing cv-qualifier from &i.

所以,如果你把你的程序改正为

const int *ptr = (const int *) &i;
Run Code Online (Sandbox Code Playgroud)

为了满足回收,你会得到一个错误

*ptr = 99;
Run Code Online (Sandbox Code Playgroud)

error: *ptr is const

从而使问题显而易见.

故事的道德:

法律角度来看,你编写了错误的代码,因为它是-by语言定义 - 依赖于未定义的行为.

道德的角度来看:编译器保持不公平的行为:在接受后执行const-inlining(替换cout << icout << 5)是一种自我矛盾,至少应该警告不连贯的行为.如果它想做一件事就不能接受另一件事,反之亦然. (int*)&i

因此,检查是否有可以设置警告的标志,如果没有,请向编译器制造商报告其不公平性:它没有警告其自身的矛盾.