为什么此代码打印0

时间:2013-10-15 23:01:25

标签: c++ variables pointers memory

为什么以下代码打印0?即为什么变量a位于变量d之后,即使它们之间正在声明指针变量c

#include<iostream>
using namespace std;

int main () {
    unsigned int a = 100;
    unsigned int &b = a;
    unsigned int *c = &b;
    unsigned int d = (unsigned int)(c);
    int e = &d - c;
    int &f = e;
    e ++;
    cout << e << " " << endl;
    return 0;
}

3 个答案:

答案 0 :(得分:2)

向后工作:

e ++;
cout << e << " " << endl;

如果打印0,则执行此代码之前e的值必须为-1

int e = &d - c;

因此上述地址减法的结果必须是-1

unsigned int a /* = whatever, the value of a doesn't matter */;
unsigned int &b = a;
unsigned int *c = &b;
unsigned int d /* = whatever, the value of d doesn't matter */;

b是对a的引用,因此&b相当于&a

因此&d - c相当于&d - &a,并且该减法产生-1

结论:在d的地址之后,sizeof (unsigned int)的地址为a字节。 (指针减法按指向类型的大小缩放。)

可能。

实际上,减去指向两个独立定义对象的指针的行为是 undefined 。该标准几乎没有说它应该做什么。

实际上,编译器可能会为指针减法生成最简单的代码,而这个简单的代码可能会将不相关的指针视为它们具有可比性,即使该语言没有说明他们是。

根据您的程序输出,bd恰好彼此相邻分配。没有什么说声明的变量必须按照声明它们的顺序进行分配。如果您希望以定义顺序在内存中分配对象,请将它们放入struct或将它们作为数组的元素。

如果您在不同的系统上运行它,或者在具有不同编译器的同一系统上运行相同的程序,或者在具有不同编译器选项的相同编译器的同一系统上运行,则同一程序也可能产生不同的结果。原则上,它甚至可以表现出不同的一切,但是在月亮的不同阶段。

允许编译器假设您的代码行为已明确定义,并执行仅在给定假设的情况下有效的转换。实际上,通过减去两个不相关的指针,你已经向编译器承诺它们都指向同一个数组对象的元素或者只是指向它的末尾(其中单个对象被视为1元素数组)(或者两者都是是空指针;这是C和C ++之间的一个区别)。你已经骗了编译器,这意味着你没有进一步的责任。

不要那样做。

答案 1 :(得分:0)

除非您使用自己的内存管理系统明确放置对象,否则它们在内存中的相对位置将依赖于编译器和系统。

答案 2 :(得分:-1)

您的行int e = &d - c;正在减去2 unsigned int *

在内存中,&dc长8个字节(它取决于您的系统,但我们假设int是4个字节)。实际上,您可以通过以下方式构建堆栈:

unsigned int a = 100;                // &a is 0x0
unsigned int &b = a;                 // &b is 0x0 (it's just an alias)
unsigned int *c = &b;                // &c is 0x4
unsigned int d = (unsigned int)(c);  // &d is 0x8

unsigned int在内存中使用4个字节。 因此,当您执行&d - c时,它必须返回2,因为您正在使用指针算术unsigned int*(4 * 2 = 8);

您可以尝试使用int e = (short*)&d - (short*)c结果4,因为short尺寸为2(2 * 4 = 8)。

您可以尝试使用int e = (char*)&d - (char*)c结果8,因为char尺寸为1(1 * 8 = 8)。

尝试打印变量和地址以了解:

#include<iostream>
using namespace std;

int main () {
  unsigned int a = 100;
  unsigned int &b = a;
  unsigned int *c = &b;
  unsigned int d = (unsigned int)(c);
  int e = (short*)&d - (short*)c;
  //int &f = e;                                                                                                                                                                  
  //e ++;                                                                                                                                                                        

  cout << "&a: " << (unsigned int)&a << endl;
  cout << "&b: " << (unsigned int)&b << endl;
  cout << "&c: " << (unsigned int)&c << endl;
  cout << "&d: " << (unsigned int)&d << endl;

  cout << endl;

  cout << " a: " << a << endl;
  cout << " b: " << b << endl;
  cout << " c: " << (unsigned int)c << endl;
  cout << " d: " << d << endl;

  cout << endl;

  cout << " e: " << e << endl;
  return 0;
}

此处,使用int e = (short*)&d - (short*)c;,结果为:

&a: 3220197356
&b: 3220197356
&c: 3220197360
&d: 3220197364

 a: 100
 b: 100
 c: 3220197356
 d: 3220197356

 e: 4