C++ 通过使用以下工具限制结构尺寸:
为什么需要这段代码C++ 通过使用以下工具限制结构尺寸:,c++,C++,为什么需要这段代码 typedef struct corr_id_{ unsigned int size:8; unsigned int valueType:8; unsigned int classId:8; unsigned int reserved:8; } CorrId; 我对它做了一些调查,发现这样我们就可以将内存消耗限制在我们需要的范围内。 例如 我想了解这些场景的真实用例?为什么我们不能像这样声明结构 ty
typedef struct corr_id_{
unsigned int size:8;
unsigned int valueType:8;
unsigned int classId:8;
unsigned int reserved:8;
} CorrId;
我对它做了一些调查,发现这样我们就可以将内存消耗限制在我们需要的范围内。
例如
我想了解这些场景的真实用例?为什么我们不能像这样声明结构
typedef struct corr_id_new{
unsigned _int8 size;
unsigned _int8 valueType;
unsigned _int8 classId;
unsigned _int8 reserved;
} CorrId_NEW;
这与编译器优化有关吗?或者,以这种方式声明结构有什么好处?它通常与pragma pack一起用于创建带有标签的位字段,例如:
#pragma pack(0)
struct eg {
unsigned int one : 4;
unsigned int two : 8;
unsigned int three : 16
};
可以出于任何目的对int32\t进行强制转换,反之亦然。这在读取遵循与语言无关的协议的序列化数据时可能很有用-您提取一个int并将其转换为struct eg,以匹配协议中定义的字段和字段大小。您也可以跳过转换,只需将int大小的块读入这样的结构,即位字段大小与协议字段大小匹配。这在网络编程中非常常见-如果要按照协议发送数据包,只需填充结构、序列化和传输即可
请注意,pragma包不是标准的C,但它可以被各种常见的编译器识别。但是,如果没有pragma pack,编译器可以自由地在字段之间放置填充,从而减少用于上述目的的使用值。它通常与pragma pack一起用于创建带有标签的位字段,例如:
#pragma pack(0)
struct eg {
unsigned int one : 4;
unsigned int two : 8;
unsigned int three : 16
};
可以出于任何目的对int32\t进行强制转换,反之亦然。这在读取遵循与语言无关的协议的序列化数据时可能很有用-您提取一个int并将其转换为struct eg,以匹配协议中定义的字段和字段大小。您也可以跳过转换,只需将int大小的块读入这样的结构,即位字段大小与协议字段大小匹配。这在网络编程中非常常见-如果要按照协议发送数据包,只需填充结构、序列化和传输即可
请注意,pragma包不是标准的C,但它可以被各种常见的编译器识别。但是,如果没有pragma包,编译器可以自由地在字段之间放置填充,从而减少用于上述目的的使用值
我想了解这些场景的真实用例
例如,某些CPU的状态寄存器的结构可能如下所示:
为了通过结构表示它,可以使用位字段:
您可以在这里看到字段不是8的倍数,因此不能使用int8\t或类似的东西
我想了解这些场景的真实用例
例如,某些CPU的状态寄存器的结构可能如下所示:
为了通过结构表示它,可以使用位字段:
您可以在这里看到,字段不是8的倍数,因此不能使用int8\u t或类似的东西。您是对的,最后一个使用unsigned\u int8的结构定义几乎等同于使用:8的定义。几乎是这样,因为字节顺序在这里会有所不同,所以您可能会发现在这两种情况下内存布局是相反的 :8表示法的主要目的是允许使用小数字节,如
struct foo {
uint32_t a:1;
uint32_t b:2;
uint32_t c:3;
uint32_t d:4;
uint32_t e:5;
uint32_t f:6;
uint32_t g:7;
uint32_t h:4;
}
为了尽量减少填充,我强烈建议自己学习填充规则,它们并不难掌握。如果您这样做,您就可以知道您的unsigned _int8版本没有添加任何填充。或者,如果您不想学习这些规则,只需在结构上使用_attribute ___; packed _;,但这可能会导致严重的性能损失。您是对的,最后一个使用unsigned int8的结构定义几乎等同于使用:8的定义。几乎是这样,因为字节顺序在这里会有所不同,所以您可能会发现在这两种情况下内存布局是相反的 :8表示法的主要目的是允许使用小数字节,如
struct foo {
uint32_t a:1;
uint32_t b:2;
uint32_t c:3;
uint32_t d:4;
uint32_t e:5;
uint32_t f:6;
uint32_t g:7;
uint32_t h:4;
}
为了尽量减少填充,我强烈建议自己学习填充规则,它们并不难掌握。如果您这样做,您就可以知道您的unsigned _int8版本没有添加任何填充。或者,如果您不想学习这些规则,只需在结构上使用_属性_;打包_;,但这可能会导致严重的性能损失。让我们看一个简单的场景
typedef struct student{
unsigned int age:8; // max 8-bits is enough to store a students's age 255 years
unsigned int roll_no:16; //max roll_no can be 2^16, which long enough
unsigned int classId:4; //class ID can be 4-bits long (0-15), as per need.
unsigned int reserved:4; // reserved
};
上述情况下,所有工作仅在32位中完成
但是如果你只使用一个整数,它就需要4*32位
如果我们将年龄作为32位整数,它可以存储在0到2^32的范围内。但别忘了,一个正常人的年龄最多只有100、140或150,即使是在这个年龄学习的人,也需要最多8位来存储,那么为什么要浪费剩余的24位呢。让我们看一个简单的场景
typedef struct student{
unsigned int age:8; // max 8-bits is enough to store a students's age 255 years
unsigned int roll_no:16; //max roll_no can be 2^16, which long enough
unsigned int classId:4; //class ID can be 4-bits long (0-15), as per need.
unsigned int reserved:4; // reserved
};
上述情况下,所有工作仅在32位中完成
但是如果你只使用一个整数,它就需要4*32位
如果我们将年龄作为32位整数,它可以存储在0到2^32的范围内。但别忘了一个正常人的最大年龄只有100岁或以上
140或150位,即使是在这个年龄学习的人,也需要最多8位来存储,那么为什么要浪费剩余的24位呢。实际上,你应该将这两种方法结合起来。。。或者使用pack/pack您确定输出是4 16,而不是16 4吗?谢谢。做了那些改变。可能是你的复制品假设原程序员知道他在做什么。这并不总是一个正确的假设。事实上,你应该结合这两种方法。。。或者使用pack/pack您确定输出是4 16,而不是16 4吗?谢谢。做了那些改变。可能是你的复制品假设原程序员知道他在做什么。这并不总是一个正确的假设。你的答案是+20