2015-11-07 103 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)