0

为什么下面的代码打印 0?即为什么 variablea位于 variable 之后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;
}
4

3 回答 3

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

So&d - c等价于&d - &a,并且那个减法产生-1

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

大概。

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

在实践中,编译器可能会为指针减法生成最简单的代码,并且该简单代码可能会将不相关的指针视为它们是可比较的,即使语言没有说它们是可比的。

考虑到您的程序的输出,这很可能b并且d恰好是彼此相邻分配的。没有说声明的变量必须按照声明它们的顺序分配。如果您希望以定义的顺序在内存中分配对象,请将它们放入 astruct或使其成为数组的元素。

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

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

不要那样做。

于 2013-10-15T23:32:53.600 回答
0

Unless you explicitly place objects using your own memory management system, their relative positions in memory will be compiler- and system-dependent.

于 2013-10-15T23:11:14.147 回答
-1

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

在内存中,&d是 8 个字节c(这取决于您的系统,但我们假设 anint是 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 int4 个字节。所以,当你在做的时候&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
于 2013-10-15T23:52:02.867 回答