【问题标题】:Little-endian byte order (in C)Little-endian 字节顺序(在 C 中)
【发布时间】:2018-08-09 14:46:32
【问题描述】:

我听说在 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”。

这是因为小端字节序吗?

【问题讨论】:

  • 你在这里处理的是 bytes,所以字节序在这里不会改变任何东西。
  • 字符串没有字节序。
  • 字符串也不会向后复制
  • (旁注:您不需要标题中的(in C),用c 自动标记您的问题)
  • 只需查找“endian”。我相信维基百科有很好的描述。

标签: c memory char stack endianness


【解决方案1】:

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

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

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

【讨论】:

    【解决方案2】:

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

    具有“字节序”的原因,特别是小字节序,因为大字节序是更自然的形式,这是一个问题,即处理器如何在给定数据总线的情况下将字节从内存移入和移出其寄存器小于原生寄存器宽度

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

    【讨论】:

      【解决方案3】:

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

      字符是如何存储的

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

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

      如何存储整数

      考虑一个像 5678 这样的整数。这个整数不适合一个 8 位字节。在二进制中,它是 10110 00101110(可读性空间)。这需要至少两个字节来存储,一个字节包含 10110,一个字节包含 00101110。

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

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

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

      堆栈的组织方式

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

      堆栈增长主要以块的形式发生。当一个函数被调用时,它会在堆栈中添加一些空间来为其本地数据腾出空间。所以它将堆栈指针减少了一些量,然后使用该空间。

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

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

      【讨论】:

      • 感谢先生为您解惑。正是我希望的答案。 +1
      • 只是出于好奇,在具有缓冲区溢出漏洞的程序接受字符串输入的情况下会发生什么,因此溢出的字符将转到下一个内存地址。这是字节序决定字符顺序以及它们如何存储在内存中的场景吗?
      • @Heineken:在缓冲区溢出中,通常程序以通常的顺序写入缓冲区,并且它得到的字符串比它设计的要长(并且无法检查长度并停止如果字符串太长),因此它继续写入超出缓冲区的末尾。写入字节的顺序不会改变;它走得太远了。
      猜你喜欢
      • 2010-10-16
      • 2022-12-12
      • 1970-01-01
      • 2012-10-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-06-30
      • 1970-01-01
      相关资源
      最近更新 更多