C++ 用字符重写结构,为什么在英特尔处理器上得到以下结果?

C++ 用字符重写结构,为什么在英特尔处理器上得到以下结果?,c++,intel,bit,C++,Intel,Bit,我被以下代码弄糊涂了: #include <iostream> using namespace std; struct bit { int a:3; int b:2; int c:3; }; int main(int argc, char* argv[]) { bit s; char *c = (char*)&s; *c = 0x99; cout << s.a <<end

我被以下代码弄糊涂了:

#include <iostream> 

using namespace std;

struct bit 
{
    int a:3; 
    int b:2; 
    int c:3; 
}; 
int main(int argc, char* argv[]) 
{ 
    bit s; 
    char *c = (char*)&s; 
    *c = 0x99; 
    cout << s.a <<endl <<s.b<<endl<<s.c<<endl; 
    return 0; 
}
#包括
使用名称空间std;
结构钻头
{
INTA:3;
INTB:2;
INTC:3;
}; 
int main(int argc,char*argv[])
{ 
位s;
char*c=(char*)&s;
*c=0x99;

cout0x99是10011001二进制是10011001,看起来非常像1,-1,-4(按相反顺序)。是的,它是8个最低有效位


我相信signedness已经把您弄糊涂了,所以您可能希望在结构中使用
unsigned int
。如果不是signedness,那么请更具体一些。

首先,因为您使用int对结构成员进行签名

*ch = 0x00  -> s.a = 0 s.b = 0 s.c = 0
*ch = 0x01  -> s.a = 1 s.b = 0 s.c = 0
*ch = 0x04  -> s.a = -4 s.b = 0 s.c = 0
*ch = 0x05  -> s.a = -3 s.b = 0 s.c = 0

取决于您的Endian机器是大还是小。

这里至少涉及三个问题。第一个问题(已经存在) 第二个是位的大小 是。(在很多编译器上是四个字节。)如果更多 超过一个字节,则您的
char*
将无法访问所有字节。并且 最后,还有一个问题是编译器如何安排位, 一些编译器将从 从高阶位铺设,从低阶位铺设。 如果编译器只对
位使用一个8位
字符
,则 根据顺序,您可能会得到{[+-]4,3或-1,1}或 相反。更不用说当用作位字段时,纯
int
可以 可以是
有符号整数
无符号整数
(因此[+-]4和3或-1)。(在 所有其他上下文,纯
int
signed int
,并且从QoI的角度来看 视图,这就是我在这里所期望的,即使只是出于一致性的原因。)

一般来说,如果您的唯一目标是在内存中保存内存 结构,位域是可以的,但一旦你
试图匹配某些外部表示。

由于使用了
int
,您的结构的大小超过了1个字节,但您试图为结构的整个内容分配1个字节的值。这将不起作用。请将结构更改为使用
char
而不是
int
,特别是因为您正在使用
char*
指定值的指针。结构成员指定的总位数应与所用基础数据类型的字节大小相匹配,例如:

struct bit
{
    char a:3;
    char b:2;
    char c:3;
};  
在相关说明中,您可以使用
union
来避免
char*
指针:

union bit
{
    struct
    {
        char a:3;
        char b:2;
        char c:3;
    };
    char value;
};  

int main(int argc, char* argv[])
{
    bit s;
    s.value = 0x99;
    std::cout << (int)s.a << std::endl << (int)s.b << std::endl << (int)s.c << std::endl;
    return 0;
}     
联合位
{
结构
{
字符a:3;
字符b:2;
字符c:3;
};
字符值;
};  
int main(int argc,char*argv[])
{
位s;
s、 值=0x99;

std::cout@AndersK.,不,它在Linux上machine@AndersK.无论打包方式如何,结构通常为4字节,因为它由单个32位整数组成,其中包含8位字段。(当然,这不是标准规定的。但这是在现代PC上任何正常实现中都会得到的。)嗯,所以g++是疯狂的?;)使用
#pragma pack(1)
sizeof(struct bit)产生1。当然不会影响结果。是的,“不管打包”位有点粗体。因为什么时候is
cout-Endianness在这里不是问题,
bit
的大小根本不重要,
char*
无意访问它的所有部分,我认为编译器如何排列位是由标准定义的,它以您声明它们的方式排列它们。唯一的部分是由标准是字段的默认符号。@MichaelKrelin hacker Endianness在
sizeof(bit)
大于1时起作用;
char
不会访问结构的所有位(它访问哪些位取决于Endianness)。“类对象中的位字段分配由实现定义”(§9.6/1).在实践中,我所知道的所有编译器都按照指定的顺序排列位,从“单词”的一端或另一端开始(对于“单词”的实现定义含义),但我认为甚至不需要这样做。Endianness在解释结果时并不重要,OP发现这很可疑,我不够清楚,抱歉。