记一次小端序内存的实际体现

Last

起因

  • 记得去年在完成 NJU PA 的时候,遇见一位群友在读取 elf 文件并校验魔数的时候遇到的问题:他读取出的魔数是字节颠倒的。

  • 他读出的魔数是 46 4c 45 7f,但实际上应当为 7f 45 4c 46。从表面上看,就好像是因为小端序机器中内存的存储方式一样,以字节为单位颠倒过来。

  • 我当时仔细检查他的代码后发现,他使用 fread 函数的时候出现了错误,填反了 sizen_count 这两个参数:

    1
    2
    3
    4
    uint32_t ident;
    FILE *fp = fopen("./a.out", "rb");

    fread(&ident, 1, 4, fp);
  • 我想当然的认为,这就是导致最后字节顺序倒转的原因。

  • 但实际上当时我们都没有尝试调转这两个参数的位置后,输出的内容会不会恢复正常——那位朋友后来得知了可以 #include <elf.h> 并且使用其中定义好的数据结构承接 elf 文件中的内容,也就不需要这种方法了。

    1
    2
    3
    4
    5
    ElfW(Ehdr) ELF_header;
    fread(&ELF_header, sizeof(ELF_header), 1, file);
    // check file ident
    if (memcmp(ELF_header.e_ident, ELFMAG, SELFMAG) != 0)
    Assert(0, ANSI_FMT("Not an ELF file: %s.", ANSI_FG_RED), elfFile);

实际原因

  • 时隔半年我看到考研群里大伙在讨论大小端序,突然想起来上面这位朋友遇到的问题,便想着重现一下并且和群友们分享。但是我突然发现我始终无法获取一个相反的文件内容,不管 size 是不是 1。

  • 询问大模型后我才恍然大悟,原来真正的问题并不在于 fread,而是用来存放读取到的内容的变量类型: uint32_t

  • 真正的原因在于从文件中读取的内容被存在了一个 uint32_t 类型的变量里,而这类变量在小端序机器的内存中存放的方式正是字节颠倒的。此时使用 %x 作为占位符将其输出时,就会得到一个字节颠倒的结果。

  • 下面这两个函数可以很好的展示这一差异:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    void read_elf_uint() {
    uint32_t ident;
    FILE *fp = fopen("./a.out", "rb");

    fread(&ident, 4, 1, fp);

    printf("reversed: 0x%x\n", ident);

    fclose(fp);
    }

    void read_elf() {
    unsigned char ident[4];
    memset(ident, 0, 4);
    FILE *fp = fopen("./a.out", "rb");

    fread(ident, 4, 1, fp);

    printf("correct: 0x");
    for (int i = 0; i < 4; i++) {
    printf("%x", ident[i]);
    }
    printf("\n");

    fclose(fp);
    }

感慨

  • C 真是门艰深又麻烦的语言,为了灵活性导致了非常多隐形的复杂度。
  • Title: 记一次小端序内存的实际体现
  • Author: Last
  • Created at : 2025-05-14 22:03:05
  • Link: https://blog.imlast.top/2025/05/14/edian/
  • License: This work is licensed under CC BY-NC-SA 4.0.
Comments
Nickname
Email
Website
0/500
  • OωO
  • |´・ω・)ノ
  • ヾ(≧∇≦*)ゝ
  • (☆ω☆)
  • (╯‵□′)╯︵┴─┴
  •  ̄﹃ ̄
  • (/ω\)
  • ∠( ᐛ 」∠)_
  • (๑•̀ㅁ•́ฅ)
  • →_→
  • ୧(๑•̀⌄•́๑)૭
  • ٩(ˊᗜˋ*)و
  • (ノ°ο°)ノ
  • (´இ皿இ`)
  • ⌇●﹏●⌇
  • (ฅ´ω`ฅ)
  • (╯°A°)╯︵○○○
  • φ( ̄∇ ̄o)
  • ヾ(´・ ・`。)ノ"
  • ( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
  • (ó﹏ò。)
  • Σ(っ °Д °;)っ
  • ( ,,´・ω・)ノ"(´っω・`。)
  • ╮(╯▽╰)╭
  • o(*////▽////*)q
  • >﹏<
  • ( ๑´•ω•) "(ㆆᴗㆆ)
  • 😂
  • 😀
  • 😅
  • 😊
  • 🙂
  • 🙃
  • 😌
  • 😍
  • 😘
  • 😜
  • 😝
  • 😏
  • 😒
  • 🙄
  • 😳
  • 😡
  • 😔
  • 😫
  • 😱
  • 😭
  • 💩
  • 👻
  • 🙌
  • 🖕
  • 👍
  • 👫
  • 👬
  • 👭
  • 🌚
  • 🌝
  • 🙈
  • 💊
  • 😶
  • 🙏
  • 🍦
  • 🍉
  • 😣
  • 颜文字
  • Emoji
  • Bilibili
0 comments
No comment
On this page
记一次小端序内存的实际体现