C.结构填料

Structure packing in C

本文关键字:结构      更新时间:2023-10-16

我有一个结构:

**struct PROCESSING
{
    PROCESSOR Byte ;
    uint16_t count ;
    uint8_t overrange ;
    Status status ;
    Time timestamp ;
    float Field;
    float temperature ;
    float adc1;
    float dac1;
    float Field2;
    float Temperature;
    float adc2 ;
    float dac2 ;
};
PTC_STATIC_ASSERT_SIZE(Processing, 45U);**

这个结构的实际结构是45U,但当我构建时,我得到了一个错误:
"sizeof对不完整类型的无效应用"

我需要把它装到45U。

关于结构包装:

为了避免对齐和填充问题,您应该考虑。

  • 重新安排成员。

  • 自己添加填充物。

  • 告诉编译器将每个成员的边界更改为1个字节。

例如:

#pragma pack(push)
#pragma pack(1)
struct PROCESSING
{
    PROCESSOR Byte ;
    uint16_t count ;
    uint8_t overrange ;
    Status status ;
    Time timestamp ;
    float Field;
    float temperature ;
    float adc1;
    float dac1;
    float Field2;
    float Temperature;
    float adc2 ;
    float dac2 ;
};
#pragma pack(pop)

重新对齐以尽可能防止填充。

struct PROCESSING
{
    PROCESSOR Byte ; // 1 byte
    Status status ;  // 1 byte
    char __padding[2]; // 2 bytes
    uint16_t count ;   // 2 byte
    uint8_t overrange ; // 1 byte
    char _padding;      // 1 byte
    Time timestamp ; // 8 bytes
    float Field;
    float temperature ;
    float adc1;
    float dac1;
    float Field2;
    float Temperature;
    float adc2 ;
    float dac2 ;
};

标准不能保证默认情况下不应用填充
你应该确信一件事。在结构的开头不会有任何填充,之后你就可以自己了-默认情况下-。

我不知道所有用户定义的类型是如何定义的,但您的直接问题似乎是您的PROCESSING结构在某种程度上没有完全定义。也许您缺少适当头文件的#include或其他内容。一旦解决了这个问题,如果你需要更多关于编译器如何在内存中布局结构的信息,你可以创建一些临时调试代码,比如这样(注意,我已经随意添加了你的类型的定义,这些定义可能与你自己的定义不匹配)。。。。

typedef char PROCESSOR;
typedef char Status;
struct Time
{
char t[8];
};

struct PROCESSING
{
    PROCESSOR Byte ;
    uint16_t count ;
    uint8_t overrange ;
    Status status ;
    Time timestamp ;
    float Field;
    float temperature ;
    float adc1;
    float dac1;
    float Field2;
    float Temperature;
    float adc2 ;
    float dac2 ;
};

int main()
{
    PROCESSING p;
    printf("Member          Size  Offsetn"
        "-------------- ------ ------n");
    #define MACROS_MAKE_THE_WORLD_GO_AROUND(structMember) 
            printf("%14s ", #structMember); 
            printf(" %3d ", sizeof(p.structMember)); 
            printf("  %3dn", offsetof(PROCESSING,structMember));
    MACROS_MAKE_THE_WORLD_GO_AROUND(Byte)
    MACROS_MAKE_THE_WORLD_GO_AROUND(count)
    MACROS_MAKE_THE_WORLD_GO_AROUND(overrange)
    MACROS_MAKE_THE_WORLD_GO_AROUND(status)
    MACROS_MAKE_THE_WORLD_GO_AROUND(timestamp)
    MACROS_MAKE_THE_WORLD_GO_AROUND(Field)
    MACROS_MAKE_THE_WORLD_GO_AROUND(temperature)
    MACROS_MAKE_THE_WORLD_GO_AROUND(adc1)
    MACROS_MAKE_THE_WORLD_GO_AROUND(dac1)
    MACROS_MAKE_THE_WORLD_GO_AROUND(Field2)
    MACROS_MAKE_THE_WORLD_GO_AROUND(Temperature)
    MACROS_MAKE_THE_WORLD_GO_AROUND(adc2)
    MACROS_MAKE_THE_WORLD_GO_AROUND(dac2)
    #undef MACROS_MAKE_THE_WORLD_GO_AROUND
    printf("n   Total size of PROCESSING struct: %d bytesnn", sizeof(p));
}

当你运行它时,你会看到这样的东西:

Member          Size  Offset
-------------- ------ ------
          Byte    1     0
         count    2     2
     overrange    1     4
        status    1     5
     timestamp    8     6
         Field    4    16
   temperature    4    20
          adc1    4    24
          dac1    4    28
        Field2    4    32
   Temperature    4    36
          adc2    4    40
          dac2    4    44
   Total size of PROCESSING struct: 48 bytes

一旦你有了这些,你就可以开始弄清楚你可能需要做什么来使你的结构与嵌入式系统的结构布局相匹配,这可能比简单地使结构具有相同的整体尺寸更复杂。但其他人给出的#pragma暗示可能是一个良好的开端。注意编译器添加的填充,您可以通过添加"size"列来计算;将它与"offset"列进行比较,如果它们不匹配,那么就知道编译器插入了一些填充。