C 数据是如何按照“位”级别存储的;Endianness“是什么;?

C 数据是如何按照“位”级别存储的;Endianness“是什么;?,c,pointers,endianness,bit,C,Pointers,Endianness,Bit,我读了关于Endianness的书,理解了蹲下 所以我写了这个 main() { int k = 0xA5B9BF9F; BYTE *b = (BYTE*)&k; //value at *b is 9f b++; //value at *b is BF b++; //value at *b is B9 b++; //value at *b is A5 } k等于A5 B9 BF 9F 和(字节)指针“walk”o/p为9

我读了关于Endianness的书,理解了蹲下

所以我写了这个

main()
{
    int k = 0xA5B9BF9F;

    BYTE *b = (BYTE*)&k;    //value at *b is 9f
    b++;    //value at *b is BF
    b++;    //value at *b is B9
    b++;    //value at *b is A5
}
k
等于
A5 B9 BF 9F

和(字节)指针“walk”o/p为
9F BF b9 A5

所以我知道字节是向后存储的…好的

~

所以现在我想它是如何存储在位级别的

我的意思是“9f”(1001111)是否存储为“f9”(1111001)

所以我写了这个

int _tmain(int argc, _TCHAR* argv[])
{
    int k = 0xA5B9BF9F;
    void *ptr = &k;
    bool temp= TRUE;
    cout<<"ready or not here I come \n"<<endl;

    for(int i=0;i<32;i++)
    {   
        temp = *( (bool*)ptr + i );
        if( temp )
            cout<<"1 ";
        if( !temp)
            cout<<"0 ";
        if(i==7||i==15||i==23)
            cout<<" - ";
   }
}
int-tmain(int-argc,_-TCHAR*argv[]
{
int k=0xA5B9BF9F;
void*ptr=&k;
布尔温度=真;

cout您的机器几乎肯定无法寻址内存的各个位,因此字节内位的布局毫无意义。Endianness仅指多字节对象内字节的顺序

为了让你的第二个程序有意义(虽然没有任何理由这么做,因为它不会给你任何有意义的结果),你需要学习位运算符-尤其是这个应用程序的
&

这一行:

temp = *( (bool*)ptr + i );
…当您执行这样的指针算术时,编译器会按您添加的数字乘以所指向对象的大小来移动指针。因为您正在将void*强制转换为bool*,编译器会将指针移动一个“bool”大小,这可能只是封面下的一个int,所以您将从比您想象的更远的地方打印出内存

您无法在一个字节中寻址各个位,因此询问它们的存储方式几乎毫无意义。(您的机器可以按任何方式存储它们,但您无法分辨)。您可能唯一关心的是,当您通过I2C或RS232或类似的物理接口实际吐出位时,您必须一个接一个地吐出位。尽管如此,协议将定义吐出位的顺序,并且设备驱动程序代码必须在两者之间进行转换“值为0xAABBCCDD的int”和“协议顺序中的位序列11100011…[无论什么]”

,正如您通过实验发现的那样,指的是对象中字节的存储顺序

位的存储方式并不不同,它们总是8位,并且总是“人类可读”(高->低)

现在我们已经讨论了您不需要代码…关于您的代码:

for(int i=0;i<32;i++)
{   
  temp = *( (bool*)ptr + i );
  ...
}

为了完整起见,机器是用字节顺序和位顺序来描述的

“英特尔x86”被称为“一致小端”,因为随着内存地址的增加,它以LSB到MSB的顺序存储多字节值。其位编号约定为b0=2^0,b31=2^31

摩托罗拉68000被称为不一致的Big-Endian,因为随着内存地址的增加,它以MSB到LSB的顺序存储多字节值。它的位编号约定为b0=2^0,b31=2^31(与intel相同,这就是它被称为“不一致”Big-Endian的原因)

32位IBM/Motorola PowerPC被称为一致的Big-Endian,因为随着内存地址的增加,它以MSB到LSB的顺序存储多字节值。其位编号约定为b0=2^31,b31=2^0

在正常的高级语言使用下,位顺序对开发人员来说通常是透明的。当用汇编语言编写或使用硬件时,位编号确实起作用。

Byte Endianness 在不同的机器上,此代码可能会给出不同的结果:

union endian_example {
   unsigned long u;
   unsigned char a[sizeof(unsigned long)];
} x;

x.u = 0x0a0b0c0d;

int i;
for (i = 0; i< sizeof(unsigned long); i++) {
    printf("%u\n", (unsigned)x.a[i]);
}

在这种情况下,位的结尾取决于编译器。
y
应该是
事物
中的最高或最低有效位吗?谁知道呢?如果您关心位顺序(描述诸如IPv4数据包头的布局、设备的控制寄存器或文件中的存储格式等内容)那么,您可能不想担心某些不同的编译器会以错误的方式执行此操作。此外,编译器在如何处理位字段方面并不总是像人们希望的那样聪明。

请不要在将来对代码使用HTML格式-使用SO代码格式选项,您将获得语法高亮显示和其他好处。字节向后存储是小尾数。按顺序存储的字节是大尾数。Endianness并不意味着字节是向后存储的。我知道如何使用showbits函数打印位…使用和掩码以及所有。但是位不是在存储时打印的。甚至不是存储时打印的“遵循字节顺序…@bakra,我希望你的
showbits
例程只是从MSB到LSB顺序。正如我在回答中提到的,它这样做并不能提供关于你的计算机存储位的方式的任何有意义的信息,因为这对你没有任何关系(也没关系,因为它们无论如何都不可寻址).1,回答得好。像您描述的逐位输出通常称为“MSB优先”或“LSB优先”,而不是“big-endian”或“little-endian”,以明确预期的行为。感谢您的回复。我没有得到的是“地址和整数”?我总是&ed 2个值…你确定这会起作用吗?@bakra:抱歉,已编辑。如果你将ptr强制转换为
无符号int
,我确定它会起作用。只是尝试确定一下。
union endian_example {
   unsigned long u;
   unsigned char a[sizeof(unsigned long)];
} x;

x.u = 0x0a0b0c0d;

int i;
for (i = 0; i< sizeof(unsigned long); i++) {
    printf("%u\n", (unsigned)x.a[i]);
}
struct thing {
     unsigned y:1; // y will be one bit and can have the values 0 and 1
     signed z:1; // z can only have the values 0 and -1
     unsigned a:2; // a can be 0, 1, 2, or 3
     unsigned b:4; // b is just here to take up the rest of the a byte
};