-5

I realized, what if i define const int into the body of c++ function and then use the address arithmetic to change the value of the constant( its on the stack, isn't it? ). i got this code:

const int a = 10;
int b = 100;

int * c = &b;
c++;

cout << "&a: " << &a << endl;
cout << " c: " << c << endl;


*c = 100500;

cout << " a: " << a << endl;
cout << "*c: " << *c << endl;

and i got this output

&a: 0x7ffff63866a8
c: 0x7ffff63866a8

 a: 10
*c: 100500

So, addresses are the same, but values are different. Can someone explain me this result? Thanks! p.s. i tried on GCC, Clang and VS

4

6 回答 6

5

有人可以解释一下这个结果吗?

与通过无效指针算术或其他恶作剧以无效方式访问对象的任何尝试一样:未定义的行为。

这里发生的是编译器假设 的值a不会改变,并将其优化为编译时常量。允许这样做,因为您已经声明了它const并因此声明它不会改变。

它在堆栈上,不是吗?

由于您还获取了它的地址(当您 print 时&a),它确实在堆栈上分配了一个地址;但是程序不需要从该地址读取来获取值,因为它已经知道是 10。

当然,这一切都是未定义的,所以如果它为你点了一个披萨,这个程序也同样有效。

于 2013-09-23T17:30:32.183 回答
3

你的程序到处都是未定义的行为......

b增加地址将使您到达的假设a是虚假的,它可以或它不能。然后,您将使用标准不安全派生指针中调用的内容来修改 const 对象 ( a),这也是未定义的行为。任何事情都有可能发生。

真正发生的事情(在你的实现中,解释你的结果,但你不能依赖它,因为这是未定义的行为)是你a通过获取它的地址来强制在堆栈中分配,并且你得到了一个指向它的指针。您修改了该值,并更新了内存中的地址。但是,在表达式中:cout << " a: " << a << endl;编译器知道a是一个常数,因此它的值只能是10,所以它把代码转换成cout << " a: " << 10 << endl;,以避免必须去内存获取值。

于 2013-09-23T17:30:41.433 回答
2

它在堆栈上,不是吗?

不,你的期望是错误的。C++ 没有任何堆栈的概念,更不用说不同的自动变量如何相对于彼此存储在内存中。您正在尝试做的是简单的未定义行为。

在您的情况下,编译器会优化a掉,因为标准允许它们进行优化,并且您得到的结果不必有任何意义,因为它无论如何都是 UB。

于 2013-09-23T17:29:53.970 回答
2
const int a = 10;
int b = 100;

好的。

int * c = &b;

好的,但是很傻,我的错误计开始转动了。

c++;

Bug-o-meter 现在位于黄色区域。

cout << "&a: " << &a << endl;

好的

*c = 100500;

Bug-o-meter 挂钩。调用了未定义的行为。世界爆炸,你被解雇。

c++将指针移动到int内存中的下一个。指针数学是可以的,但此时您可以使用c的只是将指针与另一个指针进行比较。您不能以任何方式取消引用指针。但这就是您尝试通过它分配时所做的事情。

接下来发生的事情无关紧要,而且老实说,具有误导性。您认为现在c指向与 相同的记忆b,也许确实如此。但这只是通过未定义的行为发生的。您可能还认为的值*c是您期望的值,但这个结果是错误的。也许是,也许不是。当你打开盒子时,你打碎了小瓶——猫已经死了。你的程序也是如此。

顺便说一句,如果您试图做的是找到一种方法来欺骗编译器以便您可以更改 a const,请不要 - 严禁以const 任何方式更改 a 。

C++ 中有 a const_cast,但这也不是您可以用来更改const.

于 2013-09-23T17:36:21.553 回答
0

C++ 编译器将简单地假设您永远不会尝试更改const变量的值。

这并不意味着如果你这样做你会得到一个错误......只是编译器作者可以忽略将要发生的事情,并且发生的任何事情都将被归类为“你的错”。

于 2013-09-23T17:30:37.240 回答
0

SSCC:

#include <stdio.h>

int main ()
{
  const int a = 10;
  int b = 100;
  int *c = &b;
  printf ("a=%d, b=%d, *c=%d; &a=%p, &b=%p, c=%p\n",
    a, b, *c, (void *)&a, (void *)&b, (void *)c);

  c++;  // "c" now invalid
  printf ("a=%d, b=%d, *c=%d; &a=%p, &b=%p, c=%p\n",
    a, b, *c, (void *)&a, (void *)&b, (void *)c);

  *c = 100500;  // Undefined behavior!
  printf ("a=%d, b=%d, *c=%d; &a=%p, &b=%p, c=%p\n",
    a, b, *c, (void *)&a, (void *)&b, (void *)c);

  return 0;
}

示例输出:

a=10, b=100, *c=100; &a=0028FF18, &b=0028FF14, c=0028FF14
a=10, b=100, *c=10; &a=0028FF18, &b=0028FF14, c=0028FF18
a=10, b=100, *c=100500; &a=0028FF18, &b=0028FF14, c=0028FF18

案例 2 - 我们尝试获取 CONST A 的地址:

#include <stdio.h>

int main ()
{
  const int a = 10;
  int b = 100;
  int *c = &b;
  printf ("a=%d, b=%d, *c=%d; &b=%p, c=%p\n",
    a, b, *c, (void *)&b, (void *)c);

  c++;  // "c" now invalid
  printf ("a=%d, b=%d, *c=%d; &b=%p, c=%p\n",
    a, b, *c, (void *)&b, (void *)c);

  *c = 100500;  // Undefined behavior!
  printf ("a=%d, b=%d, *c=%d; &b=%p, c=%p\n",
    a, b, *c, (void *)&b, (void *)c);

  return 0;
}

样本输出

a=10, b=100, *c=100; &b=0028FF14, c=0028FF14
a=10, b=100, *c=2686744; &b=0028FF14, c=0028FF18
a=10, b=100, *c=0; &b=0028FF14, c=00018894
于 2013-09-23T17:35:55.660 回答