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。当然不会影响结果。是的,“不管打包”位有点粗体。因为什么时候iscout-Endianness在这里不是问题,bit
的大小根本不重要,char*
无意访问它的所有部分,我认为编译器如何排列位是由标准定义的,它以您声明它们的方式排列它们。唯一的部分是由标准是字段的默认符号。@MichaelKrelin hacker Endianness在sizeof(bit)
大于1时起作用;char
不会访问结构的所有位(它访问哪些位取决于Endianness)。“类对象中的位字段分配由实现定义”(§9.6/1).在实践中,我所知道的所有编译器都按照指定的顺序排列位,从“单词”的一端或另一端开始(对于“单词”的实现定义含义),但我认为甚至不需要这样做。Endianness在解释结果时并不重要,OP发现这很可疑,我不够清楚,抱歉。