整数在CPU/内存中的每个字节是如何存储的?

7
我已经尝试过这个。
char c[4];
int i=89;
memcpy(&c[0],&i,4);
cout<<(int)c[0]<<endl;
cout<<(int)c[1]<<endl;
cout<<(int)c[2]<<endl;
cout<<(int)c[3]<<endl;

输出结果如下:
89
0
0
0

这让我感到困惑,因为我认为数字应该像0x00000059一样保存在内存中,那么为什么c[0]是89呢?我以为它应该在c[3]中...


7
欢迎来到x86计算机的世界... - Mehrdad Afshari
2
也许更合适的是修改标题。这个问题并不是关于memcpy如何工作,而是关于整数中每个字节在你的架构中是如何存储的。 - David Rodríguez - dribeas
同意了,我该怎么做? - Pyjong
已经为您完成了 - 但是您也可以通过使用标签下方的“编辑”选项自行编辑您的帖子。在这种情况下,它就在左侧的“c ++”标签下方。 - MSalters
这是访问整数字节的正确方式吗?内存对齐等方面怎么样? - Otto Allmendinger
Otto:这是完全没问题的,因为int是POD类型,这意味着你可以将其memcpy到char数组中。至于“proper”(适当)...那就因人而异了。 - Roger Pate
6个回答

33

因为您正在运行的处理器是小端。多字节基本类型的字节顺序会被交换。在大端机器上,它将如您所期望的那样。


31
哈哈。将“stupid_idiot”作为您的屏幕名称意味着永远不必说“对不起”。 - T.E.D.
2
还要注意,您不能假设int类型的长度为4个字节。始终使用sizeof(int)。在变量大小方面,我唯一感到舒适的假设(在C中)是sizeof(char)等于1。 - Nate C-K
被几秒钟打败了 :) - Gregory Pakosz
这就是为什么我选择了这个昵称 :) ,如果你的昵称是stupid_idiot,人们通常会更简单地解释事情 :)))) 这实际上也符合我的个性 :D - Pyjong

12

这是因为你正在一个小端cpu上运行程序。此外,有关字节序的信息,请参见此处那里


9

正如Goz所指出的那样,字节序是明显的答案。

但对于那些不清楚其含义的人来说,重要的是要理解在示例中显示的字节顺序与原始int中的顺序相同。无论平台的字节序类型如何,memcpy都不会改变字节顺序。


6

因为字节顺序是任意的设计决策。一旦进入寄存器,就没有字节顺序。

当我们处理更小的单元(例如字节)时,字节顺序就会出现。这是CPU设计者可以做出的基本上是任意的决定:大端或小端。

简化情况并意识到它主要是与外围设备的连接有关,字节排序才有意义。是的,它可以通过字节寻址发现,就像您证明的那样,但通常标量值被加载和存储为单位,进入寄存器,在这种情况下,字节顺序不会改变任何东西。最重要的位在“左侧”,至少是我们通常书写数字的方式。这就是为什么在遵循语言标准使用时,<<和>>运算符在大端和小端机器上总是产生完全相同的结果。

但是,为了读取和写入数据流到外围设备,您必须选择字节顺序。这是因为外围设备本质上是字节流设备。最低地址具有最重要的位还是最不重要的位?两种方法都可以实现,而且阵营曾经相当均衡。

由于内存本身是按字节寻址的,因此在没有外围设备的情况下可能会导致不同的行为,但是这通常不会发生,除非像您所做的那样有一个故意的窥视。

想象一下一个没有字节只有32位字的CPU,被寻址为0、1、2。C编译器使char、int和long都成为32位对象。(这是由Cx9允许的。)哇,没有字节顺序问题!它是两者!但是……当我们连接第一个外围设备时会发生什么?


1.好吧,x86有别名较小寄存器的寄存器,但那是另一回事。


我也可能指出,历史上许多机器(CDC、Cray、Dec-10/20等等)都采用不同的字长制成,但除了最后一段中我想象的那个之外,其他方面都是相同的。编译器、API或库可能会为打包字符数组定义一个顺序,因此库或软件系统可能具有某种字节顺序,但底层机器仍然没有。 - DigitalRoss

2
不同的机器可能具有不同的字节顺序,但看看这段代码,思考根据字节如何排列会发生什么:
long x = 89;
short *p = (short*)&x;
short y = *p;

1
如果您希望您的应用程序具有可移植性或在团队中开发,那么您可能不希望遵循这种逻辑,因为它会导致难以捕捉的错误并延长开发时间。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接