与const和指针相关的问题

时间:2012-01-27 07:22:34

标签: 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===============

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

4 个答案:

答案 0 :(得分:6)

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

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

*ptr = 99;

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


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

由于iconst,编译器认为它不会改变。因此,它只是简单地将5内联到每个使用它的地方。这就是为什么打印i会显示5的原始值。

答案 1 :(得分:5)

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

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

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

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

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

这里的“坏”事情是编译器应该在遇到未定义的行为时发出警告强制const 应该被警告为潜在的错误,< em>特别是如果编译器执行const-inlining otimizations ,因为如果允许更改const是无意义的话,如果你指定了正确的标志(可能是-W4或 - )根据您所拥有的编译器,可以使用wall或-pedantic或类似的内容。

特别是

int *ptr = (int *) &i;

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

因此,如果您将程序更正为

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

为了满足回收,你将在

处得到一个错误
*ptr = 99;

error: *ptr is const

从而使问题变得明显。

故事的道德

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

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

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

答案 2 :(得分:2)

const int i = 5;

意味着变量iconst并且它不能/不应该被更改,它是Imuttable并且通过指针更改它会导致未定义行为

未定义的行为意味着程序格式错误,任何行为都是可能的。您的程序似乎可以按预期工作,或者甚至不会崩溃。所有安全的赌注都已关闭。

记住规则: 修改const变量是未定义的行为。不要这样做。

答案 3 :(得分:1)

您正在尝试通过未定义的指针修改常量。这意味着任何意外情况都会发生,从正确的输出到错误的输出,再到程序崩溃。