代码之家  ›  专栏  ›  技术社区  ›  Charles Salvia

ASCII字符串和字节序

  •  54
  • Charles Salvia  · 技术社区  · 16 年前

    一位和我一起工作的实习生向我展示了他在计算机科学中参加的关于字节序问题的考试。有一个问题显示了ASCII字符串“My Pizza”,学生必须展示如何在小端计算机的内存中表示该字符串。当然,这听起来像是一个棘手的问题,因为ASCII字符串不受字节序问题的影响。

    P-yM azzi
    

    #include <string.h>
    #include <stdio.h>
    
    int main()
    {
        const char* s = "My-Pizza";
        size_t length = strlen(s);
        for (const char* it = s; it < s + length; ++it) {
            printf("%p : %c\n", it, *it);
        }
    }
    

    这清楚地表明,字符串在内存中存储为“My Pizza”。一天后,实习生回到我身边,告诉我,教授现在声称C正在自动转换地址,以按正确顺序显示字符串。

    所以,我问:谁在这里?

    12 回复  |  直到 16 年前
        1
  •  30
  •   Heath Hunnicutt    16 年前

    毫无疑问,你是对的。

    ANSI C标准6.1.4规定,字符串文字通过“连接”文字中的字符存储在内存中。

    如果这个人的想法是正确的,那么当整数用作数组索引时,编译器也必须使用整数数学。许多其他谬误也会产生,这些谬误只能靠想象。

    这个人可能会感到困惑,因为(与字符串初始化器不同),多字节字符常量,如“ABCD”

        2
  •  16
  •   AnT stands with Russia    16 年前

        3
  •  14
  •   Priyanshu Jain    10 年前

        4
  •  10
  •   Dmitry Brant    13 年前

    int foo(const void *mem, int n)
    {
        const char *cptr, *end;
        for (cptr = mem, end = cptr + n; cptr < end; cptr++)
            printf("%p : %c\n", cptr, *cptr);
    }
    
    int main()
    {
        const char* s = "My-Pizza";
    
        foo(s, strlen(s));
        foo(s + 1, strlen(s) - 1);
    }
    

    gcc -S 并最终确定没有魔法。

        5
  •  9
  •   caf    6 年前

    如果我们谈论的是一个每个字符使用8位的系统,那么教授就错了。

    我经常使用实际使用16位字符的嵌入式系统,每个单词都是小字节序。在这样的系统中,字符串“My Pizza”确实会存储为“yMP ziaz”。

        6
  •  2
  •   Michael Buen    16 年前

    将表示为:

    P-yM阿齐

    它将被表示为,表示为什么?向用户表示为32位整数转储?或者在计算机内存中表示/布局为P-yM-azzi?

    如果教授说“我的披萨”将在计算机内存中表示/布局为“P-yM azzi”,因为计算机是小端架构,那么请有人来教这位教授 我认为这就是教授所有困惑的根源,我有一种预感,教授不是程序员(并不是说我看不起教授),我认为他没有办法在代码中证明他所学到的字节序。

    如果教授举一个例子,说明整数在机器中是如何根据机器的端序进行不同的表示/布局的,他的学生可以理解他所教的一切。

        7
  •  1
  •   Dinah SLaks    16 年前

    我假设教授试图通过类比来阐述字节序/NUXI问题,但当你将其应用于实际字符串时,你是对的。不要让这偏离了他试图教学生一个观点以及如何以某种方式思考问题的事实。

        8
  •  1
  •   Steve Jessop    16 年前

    您可能会感兴趣,可以在大端序机器上模拟小端序架构,反之亦然。编译器必须发出代码,这些代码会自动神奇地弄乱 char* 每当它取消引用指针时:在32位机器上,你会映射00<->11和01<-> 10.

    0x01020304 0x04

    然而,显然,小端序机器并不总是这样做,这是一个 在我看来,这位教授似乎认为实际数字“实际上”是大端序,并且对小端序架构的真正含义和/或其内存的表示方式深感困惑。

    字符串确实被“表示为” P-yM azzi 在32位l-e机器上,但只有当“representative”的意思是“按地址递增的顺序读取表示的单词,但打印每个单词的字节大端”时。正如其他人所说,这是一些调试器内存视图可能会做的,所以它确实是 内存内容的表示。但是,如果你要表示单个字节,那么更常见的是按地址递增的顺序列出它们,无论单词是存储在b-e还是l-e中,而不是将每个单词表示为多字符文字。当然,这并不是在摆弄指针,如果教授选择的代表让他认为有一些,那么这就误导了他。

        9
  •  0
  •   Brian Postow    16 年前

        10
  •  0
  •   akif    16 年前

        11
  •  0
  •   DigitalRoss    16 年前

    很难读懂教授的想法,当然编译器除了在BE和LE系统上将字节存储到相邻的递增地址外,什么也没做,但

    $ cat > /tmp/pizza
    My-Pizza^D
    $ od -X /tmp/pizza
    0000000 502d794d 617a7a69
    0000010
    $ 
    

        12
  •  0
  •   nickaknudson    13 年前

    byte s和 word address 他们。A. byte 是8位。A. word

    • 具有4字节(32位)字
    • 字对齐

    Byte Order Within Words: (a) Big Endian, (b) Little Endian

    单词中的字符和整数数据:(a)大端号,(b)小端号

    Character and Integer Data in Words: (a) Big Endian, (b) Little Endian

    参考文献

    推荐文章