【问题标题】:Little endian or Big endian小端或大端
【发布时间】:2013-04-30 00:58:54
【问题描述】:
#include <stdio.h>

union Endian
{
    int i;
    char c[sizeof(int)];
};

int main(int argc, char *argv[]) 
{
    union Endian e;
    e.i = 1;
    printf("%d \n",&e.i);
    printf("%d,%d,\n",e.c[0],&(e.c[0]));
    printf("%d,%d",e.c[sizeof(int)-1],&(e.c[sizeof(int)-1]));


}

输出:

1567599464 
1,1567599464,
0,1567599467

LSB 存储在低位地址,MSB 存储在高位地址。这不应该是大端吗?但我的系统配置将其显示为小端架构。

【问题讨论】:

  • @tez 每当您打印地址时,将它们转换为void* 并使用%p 格式说明符是正确的。%d 是一个纯粹的禁忌,因为它用于签名-整数。地址从不签名。
  • @shazin 当 OP 使用 e.i=1,e.c[0] 也获得了它的值,因为它们具有相同的地址。这就是联合的​​全部意义,与结构相反。
  • @tez 因为%p 期望,就像 %d 期望整数,而不是浮点数
  • @tez 最好遵守规则。如果您使用%u 代替`%p,有时可能会得到相同的结果,但这并不总是有保证的。所以最好坚持规则。
  • @Koushik 从与最后存储在 C 中的联合成员不同的联合成员中读取数据本身并不是 UB(在 C++ 中是这样)。您可能会得到一个陷阱表示,如果读取的成员大于存储的成员,则与存储的成员不对应的字节具有不确定的值。两者都不适用于此处,因此行为不是未定义的(但未指定,因为它取决于字节序)。

标签: c math arithmetic-expressions


【解决方案1】:

你的系统肯定是little-endian。如果是big-endian,代码如下:

printf("%d,%d,\n",e.c[0],&(e.c[0]));

将为第一个%d 打印0 而不是1。在little-endian 1 存储为

00000001 00000000 00000000 00000000
^ LSB
^Lower Address

但在big-endian 中存储为

00000000 00000000 00000000 00000001
                           ^LSB
                           ^Higher Address  

并且不要使用%d来打印变量的地址,使用%p

【讨论】:

  • 还有一个问题。在 char 数组中,与 c[1] 相比,c[0] 是否总是位于较低地址,无论系统和编译器如何??
  • @tez 是与否!!通常我们可以期望数组元素存储在从低地址到高地址开始的连续内存位置(地址总是连续,否则指针运算将不适用于数组)。但是有像stack grows backwards这样的情况。我无法用严格的语言来解释,所以你应该把它放在另一个问题中,以便像 Jonathan Leffer、David Pischer 或 Mat 这样的顶级贡献者可以回答。
  • @tez 我已经为你发布了这个问题。这是链接。 stackoverflow.com/questions/16397175/…
  • 非常感谢您的帮助。希望有一天我能有足够的知识为这个美好的社区做出贡献。
【解决方案2】:

对于little endian,最低有效位存储在第一个字节(具有最低地址)中。

这就是你所看到的,所以看起来很理智;)

【讨论】:

    【解决方案3】:
    00000001 (Hexadecimal: 32 bits)
    ^^    ^^
    MS    LS
    Byte  Byte
    

    最低地址的最低有效字节 => little-endian。整数被放入内存中,从它的小端开始。因此得名。

    Endianness

    【讨论】:

    • 恐怕您错了。您在插图中谈论的是bits,并且您使用的是与Bytes相关的MSB和LSB之类的术语b> 不是
    • little-endianbig-endian 字节中的位顺序没有区别。上图完全错误。
    • @Rüppell'sVulture 我指向一组 2 半字节,以十六进制表示。我指的是字节,而不是位。编辑使其更清晰。
    • @Rüppell'sVulture :我认为这可能是十六进制值,而不是二进制值 - 诚然很难区分。
    【解决方案4】:

    您将包含“1”(最低有效)的字节作为第一个元素(e.c[0]),将包含“0”的字节作为第二个元素(e.c[1])。这是litte endian,不是吗?

    【讨论】:

      【解决方案5】:

      你对什么是大端和什么是小端是错误的。阅读this

      【讨论】:

        【解决方案6】:

        我觉得不错。 “小端”(又名“正确的方式”:-) 表示“首先存储的低阶字节”,这正是您的代码所显示的。 (顺便说一句,您应该使用“%p”来打印地址)。

        【讨论】:

        • -1 用于调用小端的正确方法!说温度是十分之五,三单位和七十分是不对的:)
        • 我来自 C 背景。在我看来,(short)i 应该等于 *(short *)(&amp;i)
        猜你喜欢
        • 2012-03-03
        • 1970-01-01
        • 2016-06-13
        • 2011-12-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-05-09
        • 1970-01-01
        相关资源
        最近更新 更多