2015-11-07 165 views
1

这是一个滥用void* ptr(这本身就是一个糟糕的编码习惯)的样本,但是当我查看内存细节时,它会变得很有趣。这个程序为什么输出8589934593而不是4294967298?

#include <iostream> 
using namespace std; 

typedef struct { 
    long a; 

    void print() { 
    std::cout << a; 
    } 
} st; 

int main() { 
    int t[2] = {1,2}; 
    void* p = t; 
    st* spt = (st*) p; 
    spt->print(); 
    return 0; 
} 

由于long是64位,并且int是32位的,在t时的两个整数,{1,2}弥补了在structlong a的空间。

但我的问题是,既然现在{1,2}拼成a,二进制内存走线应00000000000000000000000000000001 00000000000000000000000000000010,这应该给其十进制格式4294967298。但是,实际打印输出为8589934593,即00000000000000000000000000000010 00000000000000000000000000000001。看起来12的位置实际上是交换的。

这是怎么发生的?

+0

我想'00000000000000000000000000000001 0000000000000000000000000010'实际上是4294967298 – 2015-11-07 02:06:05

+4

也许是因为你的机器使用小端。 – MikeCAT

+1

这似乎是[endianess]的一个问题(https://en.wikipedia.org/wiki/Endianness)。 – clcto

回答

2

在一个小端机的{ 1, 2 }阵列在存储器布局为字节

01 00 00 00 02 00 00 00 // addresses increase from left to right 

的以下序列当重新解释为一个64位的小端值,它产生8589934593

在大端机相同的阵列被布置为

00 00 00 01 00 00 00 02 // addresses increase from left to right 

当重新解释为一个64位的大端值,它产生4294967298

因此,您的实验只是表明您正在小端机器上运行您的代码。这里的所有都是它的。

0

我重写更便携的方式你的代码,它需要C++ 11:

#include <cstdint> 
#include <iostream> 

int main() 
{ 
    union { 
     uint32_t t[2]; 
     uint64_t a; 
    } val; 
    val.t[0] = 1; 
    val.t[1] = 2; 
    std::cout << val.a << ", " << std::hex << val.a << '\n'; 
} 

我的AMD64机器上的输出是:

8589934593,200000001

它似乎完全有效,等于uint64_t(2) << 32 | uint64_t(1)

相关问题