【问题标题】:Understanding Endianness - a variable value了解字节顺序 - 变量值
【发布时间】:2012-01-05 13:17:44
【问题描述】:

我正在使用一段代码(在本网站的其他位置找到)在运行时检查字节序。

static bool isLittleEndian()
{
  short int number = 0x1;
  char *numPtr = (char*)&number;

  std::cout << numPtr << std::endl;
  std::cout << *numPtr << std::endl;

  return (numPtr[0] == 1);
}

在调试模式下,numPtr 的值如下所示:0x7fffffffe6ee "\001"

我假设第一个十六进制部分是指针的内存地址,第二部分是它保存的值。我知道 \0 在旧式 C++ 中是空终止,但为什么它在前面?跟字节序有关吗?
在小端机器上:01 第一个字节,因此是最低有效位(字节位置 0),\0 第二个字节/最后一个字节(字节位置 1)?

此外,cout 语句不打印指针地址或其值。这是什么原因?

【问题讨论】:

  • 你定义numPtr,用了之后怎么编译?
  • 现在已经改了。以我的名义进行错误的复制和粘贴。
  • 为什么需要在运行时检查字节序。这不是每个端口的 make 文件的一部分吗?

标签: c++ endianness


【解决方案1】:

其他人已经给你一个明确的答案"\000"是什么意思,所以这是你的问题的答案:

在 little-endian 机器上:01 是第一个字节,因此是最低有效位(字节位置 0),而 \0 第二个字节/最后一个字节(字节位置 1)?

是的,这是正确的。你看看像 0x1234 这样的值,它由两个字节组成,高位 0x12 和低位 0x34。术语“小端”表示低位首先存储在内存中:

addr:   0x34
addr+1: 0x12

您是否知道“endian”一词早于计算机行业?它最初是由乔纳森·斯威夫特在他的格列佛游记一书中使用的,它描述了人们是从尖头还是圆头吃鸡蛋。

【讨论】:

    【解决方案2】:

    检查字节顺序的最简单方法是让系统为您完成:

    if (htonl(0xFFFF0000)==0xFFFF0000) printf("Big endian");
    else printf("Little endian");
    

    【讨论】:

      【解决方案3】:

      这不是\0后跟“01”,而是单个字符\001,表示八进制的数字1。那是你的字符串中“in”的唯一字节。后面还有一个字节,其值为 0,但您看不到,因为它被视为字符串终止符。

      【讨论】:

        【解决方案4】:

        对于初学者:这种类型的功能完全没有价值:在机器上 其中sizeof(int) 是 4,有 24 个可能的字节顺序。大多数 当然,没有意义,但我至少看过三个。和字节序 不是唯一影响整数表示的东西。如果你有 一个int,如果你想得到低8位,使用intValue & 0xFF,接下来的8位,(intValue &gt;&gt; 8) &amp; 0xFF

        关于你的确切问题:我猜你在描述什么 因为“看起来像这样”是您在调试器中看到的,当您中断时 回报。在这种情况下,numPtrchar*unsigned char const* 更有意义),因此调试器采用 C 风格 细绳。 0x7fffffffe6ee 是地址;接下来是什么 编译器将其视为 C 样式字符串,将其显示为字符串,即 "..."。大概,你的平台是一个传统的小端 (英特尔);指向 C 样式字符串的指针会看到序列(数字 值)1, 00 当然等同于'\0',所以它 认为这是一个字符串,其中一个字符具有 1的编码。没有编码为的可打印字符 一,它不对应于任何正常的转义序列 (例如'\n''\t' 等)。所以调试器输出它使用 八进制转义序列,'\' 后跟 1 到 3 个八进制数字。 (传统的'\0' 只是这种情况的一个特例;紧随其后的是'\' 一个八进制数字。)它输出3位数字,因为(可能) 它不想向前看以确保下一个字符不是 八进制数。 (如果序列是两个字节1, 49,例如, 49 在通常的编码中是'1',如果它只输出一个字节 对于 1 的八进制编码,结果将是“\11”,这是一个 单个字符串——对应于通常的编码 '\t'.) 所以你得到 " 这是一个字符串,\001 第一个字符 编码为 1(并且没有可显示的表示)和" 这是字符串的结尾。

        【讨论】:

        • 你见过的第三个字节序是大、小和...?
        • @edA-qamort-ora-y 1234、4321 和 3412。最后一个是 Microsoft C,在 MS-DOS 下,在 Intel 8086 上。不完全是异国情调。当然,今天还有卖的机器(Unisys),sizeof(int)是6,表示是有符号幅度,int中有8个保留位,一定是0。
        【解决方案5】:

        您看到的"\001" 只是一个字节。它可能是八进制表示法,需要三个数字才能正确表示(十进制)值 0 到 255。

        【讨论】:

          【解决方案6】:

          \0 不是 NUL,调试器将 numPtr 显示为字符串,其第一个字符是 \001 或 ASCII 中的 control-A。第二个字符是 \000,因为显示字符串时不显示 NUL,所以不显示。 'number' 的两个字符串版本在大端机器上将显示为“\000\001”,而不是在小端机器上显示为“\001\000”。

          【讨论】:

            【解决方案7】:

            此外,cout 语句不打印指针地址或 这是价值。这是什么原因?

            因为在打印时,字符和字符指针的处理方式与整数不同。

            当您打印一个字符时,它会从正在使用的任何字符集中打印该字符。通常,这是 ASCII 或 ASCII 的某些超集。 ASCII 中的值 0x1 是非打印的。

            当你打印一个 char 指针时,它不会打印地址,而是将它打印为一个以 null 结尾的字符串。

            要获得所需的结果,请将 char 指针转换为 void 指针,并将 char 转换为 int。

            std::cout << (void*)numPtr << std::endl;
            std::cout << (int)*numPtr << std::endl;
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2011-07-16
              • 2012-05-01
              • 1970-01-01
              • 2020-11-02
              • 2020-02-12
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多