Little-endian 字节顺序(在 C 中)

Little-endian byte order (in C)

我听说在 x86 处理器中,字节以 little-endian 字节顺序存储在内存中。

意味着首先存储最低有效字节。

我无法理解这个想法及其与字节如何存储在 RAM 中的关系。

例如,

#include <stdio.h>

char string[6];
scanf("%5s",string);

在上面的代码中,如果我输入 "Hello" 这个词,"o" 首先被存储(?)

据我了解,在 C 语言(以及一般编程语言中?)中,当您声明一个变量时,该变量会存储在 RAM 的 Stack 部分。所以单词“Hello”像这样存储在堆栈中:


o    <Lower memory addresses>
l
l
e
H    <Higher memory addresses>

堆栈从较高的内存地址向较低的内存地址增长,处理器从堆栈顶部(较低的内存地址)的第一个字节开始读取字节。

现在,如果我打印字符串的值,我应该会看到“olleH”。

但显然它会打印“Hello”。

这是小端字节序的原因吗?

中,您将看不到 char 数组的字节顺序问题。 sequence不会被字节顺序改变。假设它是一个 int 那么是的,该对象的字节将按照字节顺序存储在内存中。但是对于 char 数组,只不过是按特定顺序排列的字节集合。它没有改变。

请注意,如果您有 int-s 数组,那么是的,这些 int 元素会按照您指定的顺序顺序存储。但是 int 值,它的那些字节 - 将存储在小端。

另一件事是 - char 数组的每个元素都会增加内存。例如,string[0] 的地址将小于 string[1] 的地址 - 所以在这里你不能应用字节序 - 因为那样就会违反此约束。

Wikipedia 很好地描述了字节顺序,但我找不到真正的出处。

具有 "endianness" 的原因,特别是小端,因为大端是更自然的形式,是 处理器如何将字节从内存移入和移出其寄存器的问题假设数据总线小于本地寄存器宽度

例如,具有 8 位的数据总线(因此一次只能将 1 个字节从内存移动到处理器和 vv)并且具有 16 位的整数宽度,则:第一个字节被移动从内存到寄存器是最高有效字节还是最低有效字节?

为简单起见,让我们讨论一台机器,其中内存中的每个字节都有一个地址。 (有些机器的内存只组织为几个字节的字,而不是单个字节。)在这台机器中,内存就像一个大数组,所以我们可以写 memory[37] 来谈论地址 37 处的字节。

字符的存储方式

要存储字符,我们只需将它们按顺序放在连续的内存位置即可。例如,要从地址 100 开始存储字符“Hello”,我们将 H 放在 memory[100],e 放在 memory[101],l 放在 memory[102],l 放在 memory[103],以及o memory[104]。在某些语言中,我们还在 memory[105] 处放置一个零值以标记字符串的结尾。

这里没有字节序问题。字符顺序。

整数是如何存储的

考虑一个像 5678 这样的整数。这个整数放不下一个 eight-bit 字节。在二进制中,它是 10110 00101110(为了便于阅读,space)。那至少需要两个字节来存储,一个字节包含10110,一个字节包含00101110.

当我们将它存储在从位置 100 开始的内存中时,我们先放哪个字节?这是字节序问题。有些机器把high-value字节(10110)放在memory[100]里,low-value字节(00101110)放在memory[101]里。其他机器以其他顺序执行。 high-value 字节是数字的“大端”,low-value 字节是“小端”,这导致术语“字节顺序”。 (The term actually comes from Jonathan Swift’s Gulliver’s Travels.)

(此示例仅使用两个字节。整数也可以使用四个字节或更多字节。)

每当您有一个对象由较小的对象组成时,就会出现字节序问题。这就是为什么它不是单个字符的问题——每个字符进入一个字节。 (尽管没有物理原因不能在内存中以相反的顺序存储字符串。我们只是不这样做。)当一个对象有两个或更多字节时,这是一个问题。您只需选择将字节放入内存的顺序。

堆栈的组织方式

堆栈的常见实现从高地址开始,并在向堆栈添加内容时向下“增长”。没有特别的原因。我们也可以让堆栈以另一种方式工作。历史就是这样发展的。

堆栈增长主要发生在块中。调用函数时,它会向堆栈添加一些 space 为其本地数据腾出空间。所以它将堆栈指针减少了一些,然后使用 space.

但是,在 space 中,单个对象正常存储。它们不需要反转,因为堆栈向下增长。如果堆栈指针从 2400 变为 2200,而我们现在想在 2300 处放置一个对象,我们只需将其字节写入从 2300 开始的内存即可。

因此,字节顺序不受堆栈顺序的影响。