为什么此代码打印 0

Why does this code print 0

本文关键字:打印 代码 为什么      更新时间:2023-10-16

为什么下面的代码打印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;
}

向后工作:

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的地址是a地址之后sizeof (unsigned int)字节。(指针减法按指向类型的大小缩放。

可能。

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

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

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

如果在同一系统上运行同一程序,或者在具有不同编译器的同一系统上运行

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

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

别这样。

除非使用自己的内存管理系统显式放置对象,否则它们在内存中的相对位置将取决于编译器和系统。

您的行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因为大小为 2 (2*4=8 short

您可以尝试int e = (char*)&d - (char*)c结果应该8因为大小为 1 (1*8=8 char)。

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

#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