小端字节顺序(在C中)
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了小端字节顺序(在C中)相关的知识,希望对你有一定的参考价值。
我听说在x86处理器中,字节以'little-endian'字节顺序存储在内存中。意味着首先存储最低有效字节。
我无法理解这个想法及其与字节如何存储在RAM中的关系。
例如,
#include <stdio.h>
char string[6];
scanf("%5s",string);
在上面的代码中,如果我输入单词“Hello”,则首先存储“o”。(?)
根据我的理解,当你声明一个变量时,在C(和编程通用?)中,变量存储在RAM的“堆栈”部分。所以单词“Hello”会像这样存储在堆栈中:
o <Lower memory addresses>
l
l
e
H <Higher memory addresses>
堆栈从较高的内存地址向较低的内存地址增长,处理器开始从堆栈顶部的第一个字节开始读取字节(较低的内存地址)。
现在,如果我打印字符串的值,我应该看到“olleH”。但显然它会打印“Hello”。这是因为little-endian字节顺序?
为简单起见,让我们讨论一台机器,其中内存中的每个字节都有一个地址。 (有些机器的内存只被组织成具有多个字节的字,而不是单个字节。)在这台机器中,内存就像一个大数组,因此我们可以编写memory[37]
来讨论地址37处的字节。
如何存储字符
为了存储字符,我们只是按顺序将它们放在连续的存储位置。例如,要存储从地址100开始的字符“Hello”,我们将H放在memory[100]
,e位于memory[101]
,l位于memory[102]
,位于memory[103]
,o位于memory[104]
。在某些语言中,我们还在memory[105]
上设置零值以标记字符串的结尾。
这里没有端点问题。字符是有序的。
如何存储整数
考虑一个像5678这样的整数。这个整数不适合一个8位字节。在二进制中,它是1011000101110.这需要至少两个字节来存储,一个字节包含1011,一个字节包含000101110。
当我们将它存储在从位置100开始的存储器中时,我们首先放入哪个字节?这是endian问题。有些机器将高值字节(1011)放在memory[100]
中,将低值字节(000101110)放在memory[101]
中。其他机器以其他顺序执行。高值字节是数字的“大端”,低值字节是“小端”,导致术语“字节序”。(The term actually comes from Jonathan Swift’s Gulliver’s Travels.)
(此示例仅使用两个字节。整数也可以使用四个字节或更多。)
只要有一个由较小的对象构成的对象,就会出现endian问题。这就是为什么单个字符不是问题 - 每个字符都进入一个字节。 (虽然,没有物理原因你不能在内存中以相反的顺序存储字符串。我们不这样做。)当一个对象有两个或更多字节时,这是一个问题。您只需选择将字节放入内存的顺序。
如何组织堆栈
堆栈的常见实现从高地址开始,并在向堆栈添加内容时向下“增长”。没有特别的理由这样做;我们也可以让堆栈以其他方式工作。这就是事物在历史上的发展方式。
堆栈增长主要发生在块中。调用函数时,它会向堆栈添加一些空间,以便为其本地数据腾出空间。因此它会将堆栈指针减少一些,然后使用该空间。
但是,在该空间内,单个对象通常存储。它们不需要反转,因为堆栈会减少。如果堆栈指针从2400变为2200,我们现在想要将对象放在2300,我们只需将其字节写入内存,从2300开始。
因此,字节顺序不是受堆栈顺序影响的问题。
在c中,您将看到char
数组没有字节序问题。字节序不会改变序列。假设它是一个int
然后是的,该对象的字节将存储在内存中,尊重字节序。但对于char
数组,只有按特定顺序排列的字节集合。它没有改变。
请注意,如果您有int
-s数组,那么这些int
元素将按照您指定的顺序依次存储。但int
值,它的那些字节 - 将存储在小端。
另一件事是 - char
数组的每个元素都会增加内存。例如,string[0]
的地址将小于string[1]
的地址 - 所以在这里你不能应用字节序 - 因为这样就会违反这个约束。
Wikipedia很好地描述了字节序,但我找不到真正的起源。
具有“字节序”的原因,特别是作为大字节序的小端点是更自然的形式,是在给定小于本机寄存器宽度的数据总线的情况下处理器如何将字节从存储器移入和移出其寄存器的问题。
例如,具有8位数据总线(因此一次只能将1个字节从存储器移动到处理器和vv)并具有16位的整数宽度,则:是从存储器移动到寄存器的第一个字节最重要的字节或最低有效字节?
以上是关于小端字节顺序(在C中)的主要内容,如果未能解决你的问题,请参考以下文章
小端格式和大端格式(Little-Endian&Big-Endian)
小端格式和大端格式(Little-Endian&Big-Endian)