C++ 间接运算符是否更改内存表示?

C++ 间接运算符是否更改内存表示?,c++,memory,uint8t,C++,Memory,Uint8t,好吧,问这个我觉得很愚蠢,但是为什么下面的代码会输出不同的行呢 要打印第一行,我获取数组第一个字节的地址,将其解释为指向uint16_t的指针,获取值并逐个打印其位 对于第二行,我获取指向第一个字节的指针,将其解释为指向uint8\u t的指针,获取值并逐个打印它的位。然后对第二个字节执行相同的操作 由于我不修改为数组分配的内存,只以不同的方式解释它,所以我希望输出是相同的,但字节的顺序是不同的 我可能错过了一些东西,但我唯一的猜测是间接操作符做了一些我没有预料到的事情 #include <

好吧,问这个我觉得很愚蠢,但是为什么下面的代码会输出不同的行呢

要打印第一行,我获取数组第一个字节的地址,将其解释为指向uint16_t的指针,获取值并逐个打印其位

对于第二行,我获取指向第一个字节的指针,将其解释为指向uint8\u t的指针,获取值并逐个打印它的位。然后对第二个字节执行相同的操作

由于我不修改为数组分配的内存,只以不同的方式解释它,所以我希望输出是相同的,但字节的顺序是不同的

我可能错过了一些东西,但我唯一的猜测是间接操作符做了一些我没有预料到的事情

#include <iostream>
#include <string.h>


 int main() {
   uint8_t u[2];
   u[0] = 170;
   u[1] = 85;

  for(int i = 15; i >= 0; --i) {
    printf( "%u", (((*((uint16_t*)u)) >> i) & 0x0001));
  }
  printf( "\n");
  for(int i = 7; i >= 0; --i) {
    printf( "%u", (((*((uint8_t*)u)) >> i) & 0x01));
  }
  for(int i = 7; i >= 0; --i) {
    printf( "%u", (((*((uint8_t*)(u + 1))) >> i) & 0x01));
  }
}
更新#1:请忽略分配,是的,示例代码并不适用于所有操作系统,但它只是一个简化的示例


更新#2:我知道endianness,但我错过的是逻辑与物理位表示。在上面的示例中,即使物理表示保持不变,我也会打印受endianness影响的逻辑表示。非常感谢@john kugelman对此的解释

在基于英特尔的平台上,数字存储在。最低有效字节是第一个,最高有效字节是最后一个。这与我们通常阅读数字的方式相反。如果我们以小尾数而不是大尾数的顺序写数字,那么1231将被写成
3201
而不是
1023

将字节数组中的字节解释为16位整数时,第一个字节(170)被解释为最低有效字节,第二个字节(85)被解释为最高有效字节。但是,当您自己打印字节时,您会以相反的顺序打印它们。这就是不匹配的原因

是特定于平台的属性。大多数非英特尔体系结构使用更“自然”的大端顺序。不幸的是,基于Intel的体系结构是最常见的。事实上,几乎所有的网络流量都是big-endian,也称为“网络字节顺序”。当基于Intel的计算机在Internet上进行通信时,它们在发送和接收数据的过程中都会进行大量的字节交换

如果我自己打印uint16,我预计会发生这种错误匹配。我不明白的是,当我试图得到它的部分时,为什么会发生这种情况

使用位屏蔽和移位操作读取其位不会从左到右读取内存中的物理位,而是从最高有效位到最低有效位读取逻辑位。在一个小小的endian架构中,从最重要到最不重要等同于从右到左的顺序


还要注意,endianness表示交换字节,而不是位。在little-endian体系结构中,位不交换,字节交换。位无法交换,因为它们不能单独寻址。您只能使用移位和掩码来获取它们。

如果撇开可能存在的对齐错误和缺少格式字符串长度修饰符,您将面临一个endianess问题。该术语描述了长度超过最小可寻址单元(即一个字节)的数据类型如何存储在内存中

您的系统似乎对16位整数使用little endian:低位字节存储在低位地址

注意,没有理由对后两个for循环进行强制转换,因为您使用的是与数组元素相同的类型。永远不要在没有充分理由的情况下进行强制转换,并且总是尝试编写不需要强制转换的代码。强制转换可防止编译器帮助您检测类型不匹配。因此,只有当您绝对确信自己比编译器更了解自己在做什么时,才能进行强制转换。

内存中有两个字节:

0xAA

0x55

当它们被解释为16位字时,有两个可能的值

基于处理器的字节顺序:

小尾端(最低有效字节优先):0x55AA//Intel x86/x64


Big-Endian(最高有效字节优先):0xAA55//Power,ARM等。

C中没有“间接”运算符。您可能正在调用未定义的行为,因为array不需要正确对齐。您应该使用正确的格式修饰符。@Olaf,“间接”运算符(*)通过指针间接访问值“@RichardChambers:我当然不会把微软这样的人当作合格的推荐人,但我只是研究了C11标准。你是对的,他们使用这个名字,但从来没有明确提到它是
*
运算符。也许可以从十六进制的角度解释一下?是的,但如果我打印uint16本身,我预计会发生这种错误匹配。我不明白的是,当我试图得到它的比特时,为什么会发生这种情况。
0101010110101010 
1010101001010101