为什么这个程序输出8589934593而不是4294967298?

时间:2015-11-07 02:03:49

标签: c++ memory memory-management

这是一个滥用void* ptr(这本身就是一个糟糕的编码实践)的示例,但是当我查看内存细节时它会变得很有趣。

#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}中的两个整数构成long a中的struct空间{1}}。

但我的问题是,由于现在{1,2}组成a,二进制内存对齐应该是00000000000000000000000000000001 00000000000000000000000000000010,它应该以十进制格式给出4294967298。但是,实际打印输出为8589934593,即00000000000000000000000000000010 00000000000000000000000000000001。似乎12的位置实际上是交换的。

为什么会这样?

3 个答案:

答案 0 :(得分:2)

在little-endian机器上,library(gsubfn) ## Function to pass to gsubfn (use backref to get reference to orignal string) ## x is original string, y is first group (numbers), z is last (characters) f <- function(x, y, z) { n <- as.numeric(y) if(is.na(n)) n <- as.numeric(substr(y, 1, nchar(y)-1))*-1 # case: [-]\\d+- if (n == 0) return( '0' ) if (n == 1) return( z ) if (n == -1) return( paste0("-", z) ) return( paste0(n, z) ) } A[, lapply(1:ncol(A), function(i) suppressWarnings( gsubfn('([-\\d]+)(.*)', f, paste0(A[[i]], B[[i]]), backref=2))) ] # V1 V2 # 1: -a d # 2: 3b 0 # 3: -4c -f 数组在内存中按以下字节顺序排列

{ 1, 2 }

当重新解释为64位little-endian值时,它会生成01 00 00 00 02 00 00 00 // addresses increase from left to right

在big-endian机器上,相同的数组布局为

8589934593

当重新解释为64位大端值时,它会生成00 00 00 01 00 00 00 02 // addresses increase from left to right

因此,您的实验只是表明您在小端机器上运行代码。这就是它的全部内容。

答案 1 :(得分:1)

有趣的事实。在数字上,答案可以简化为的指数

2^n + 1: n=33

哪个

2^(33)+1 = 8589934593

,以二进制表示为

1000000000000000000000000000000001

可爱的二进制文件;有32个零,在这种情况下为n-1。

答案 2 :(得分: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)