字节序与类型转换

4

32位无符号整数表示的数字4,在大端序机器上是:

00000000 00000000 00000000 00000100(最高有效字节在前)

在小端序机器上是:

00000100 00000000 00000000 00000000(最高有效字节在后)

作为8位无符号整数,它在这两种机器上都表示为00000100。

现在,当将8位无符号整数转换为32位时,我总是认为在大端序机器上就是在现有字节前面添加24个零,并在小端序机器上在末尾添加24个零。但是,有人指出,在这两种情况下都是在前面添加零而不是在末尾添加零。但是,在小端序情况下,00000100不会成为最高有效字节吗?这不会导致一个非常大的数字吗?请解释我哪里错了。


这不应该是实现/架构相关的吗? - webuster
3
强制类型转换作用于被转换的值,而不是原始字节。 - Michael Burr
3
强制类型转换/类型转换操作针对的是数学上的值;(uint32_t)myByte 的值与 myByte 的值相同。 - Oliver Charlesworth
2
@IvanInTheHat:在幕后,无论需要什么来保持数学价值。 - Oliver Charlesworth
3
再次强调,位移操作是基于数值的运算定义的,而不是基于内存中比特物理顺序的。 - Oliver Charlesworth
显示剩余3条评论
3个回答

6

如果你考虑数学价值(它恰好也是大端表示),那么前导0将被添加。

C中的强制转换始终致力于保留值,而不是表示。例如,(int)1.25 的结果(*见下文)为1,而不是一些没有多少意义的东西。

正如在评论中讨论的那样,同样适用于位移(以及其他按位操作)。无论大小端,50 >> 1 == 25

(*注:通常取决于浮点数->整数转换的舍入模式)

简而言之:C语言中的运算符操作基于数学值,而不考虑表示方式。有一个例外是当您将指针强制转换为该值(如(char*)&foo)时,因为这实质上是相同数据的不同“视图”。


6

我不确定这是否回答了你的问题,但我会尝试着回答:

如果您使用 char 变量并将其强制转换为 int 变量,则在两种架构上都会得到完全相同的结果:

char c = 0x12;
int  i = (int)c;     // i == 0x12 on both architectures

如果你将一个int类型的变量强制转换成一个char类型的变量,那么在两种架构上都会得到完全相同的结果(可能被截断):

int  i = 0x12345678;
char c = (char)i;    // c == 0x78 on both architectures

但是,如果您使用char*指针读取一个int变量,则在每个体系结构上都会得到不同的结果:

int  i = 0x12345678;
char c = *(char*)&i; // c == 0x12 on BE architecture and 0x78 on LE architecture

上述示例假设 sizeof(int) == 4 (在某些编译器上可能不同)。

0
粗略地说,“字节序”是处理器查看存储在内存中的数据的属性。这意味着当特定的数据被带到CPU时,所有处理器都以相同的方式查看它。
例如:
int a = 0x01020304;

无论是小端还是大端机器,当存储在寄存器中时,04始终是最不重要的字节,01始终是最重要的字节。
问题出现在必须将此变量/数据存储在内存中时,因为内存是“按字节寻址”的。最重要的字节01应该放在最低的内存地址(大端)还是最高的内存地址(小端)?
在您的特定示例中,您展示的是表示方式,处理器看到的是LS/MS字节。
从技术上讲,小端和大端机器都会有以下内容:

00000000 00000000 00000000 00000100

在其32位宽寄存器中。当然,假设您在内存中有一个表示“4”的32位宽整数。如何将此“4”存储到/从内存检索是关于字节序的问题。

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