C ++,从“ int”到位字段的隐式截断

时间:2019-02-11 18:57:58

标签: c struct bit-fields bitstuffing

我想创建一个64位数据结构,每个位都应包含一个值。为此,我创建了一个结构如下。 (这与 J1939协议和ControlApplication NAME 有关,以防万一)

typedef struct CA_NAME {
    unsigned  IdentityNumber : 21;          // 21 bits  Byte 1.1 to 3.5 
    unsigned  ManufactorerCode : 11;        // 11 bits  Byte 3.6 to 4.8 
    unsigned  ECUInstance : 3;              // 3  bits  Byte 5.1 to 5.3 
    unsigned  functionInstance : 5;         // 5  bits  Byte 5.4 to 5.8 
    unsigned  Function : 8;                 // 8  bits  Byte 6          
    unsigned  Reserved : 1;                 // 1  bit   Byte 7.1        
    unsigned  VehicleSystem : 7;            // 7  bits  Byte 7.2 to 7.8 
    unsigned  VehicleSystemInstance : 4;    // 4  bits  Byte 8.1 to 8.4 
    unsigned  IndustryGroup : 3;            // 3  bits  Byte 8.5 to 8.7 
    unsigned  ArbitraryAddressCapable : 1;  // 1  bit   Byte 8.8        
} CA_NAME; /*64Bit NAME*/

现在我要初始化CA_NAME的对象实例

CA_NAME j1939 = {};

void Create_CA_NAME() {
    j1939.IdentityNumber = 0xFE0D32;
    j1939.ManufactorerCode = 0x57;
    ....
}

在这里我收到实时分析错误(我从ReSharper猜到)(即第一次分配) enter image description here

初始化结构实例的正确方法是什么?

1 个答案:

答案 0 :(得分:0)

常量0xFE0D32具有24个值位(并且实际上是类型int)。

您正在尝试使用超出其范围的常量初始化无符号的21位位字段IdentityNumber。编译器很友好,可以警告您这个潜在的错误。

此外,您使用C ++进行编译,这说明了原因:

  • CA_NAME j1939 = {};在C ++中不会产生错误,但在C语言中会产生错误。由于j1939是全局变量,因此实际上不需要初始化程序。如果您坚持使用显式的初始值设定项,请提供实际值或只写CA_NAME j1939 = { 0 };
  • 错误消息为abstruse,使您领略了C ++的极端复杂性。