了解字节序 - 变量值

Understanding Endianness - a variable value

本文关键字:变量值 字节 了解      更新时间:2023-10-16

我正在使用一段代码(在此站点的其他地方找到(在运行时检查字节序。

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 "01"

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

此外,cout 语句不打印指针地址或其值。 原因何在?

其他人已经对"00"的含义给出了明确的答案,所以这是对你的问题的答案:

在小端计算机上:01 第一个字节,因此最不重要(字节位 0(,\0 第二个字节/最后一个字节(字节位 1(?

是的,这是正确的。你看像0x1234这样的值,它由两个字节组成,高部分0x12和低部分0x34。术语"小端序"意味着低部分首先存储在内存中:

addr:   0x34
addr+1: 0x12

您是否知道"字节序"一词早于计算机行业?它最初由乔纳森·斯威夫特(Jonathan Swift(在他的《格列佛游记》(Gulliver's Travels(一书中使用,其中描述了人们是从尖头还是圆头吃鸡蛋。

检查

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

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

这不是后跟"01"的,而是单字符01,表示八进制中的数字 1。 这是字符串中唯一的字节。 它后面还有另一个值为零的字节,但你看不到它,因为它被视为字符串终止符。

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

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

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

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

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

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

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

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

若要获得所需的结果,请将字符指针强制转换为 void 指针,并将字符转换为 int。

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