Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/148.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 通过使用以下工具限制结构尺寸:_C++ - Fatal编程技术网

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