使用__attribute __((packed))避免c中的结构填充

the*_*t33 8 c struct

__attribute__((packed))用来避免struct padding.下面的代码工作正常,但是当我int在struct中添加一个更多的成员时,编译器会填充我的struct.

#include <stdio.h>

struct test {

    int x;
    char c1;
    char c2;
    char c3;
    char c4;
    char c5;
    // int d; Pads if I uncomment

} __attribute__((packed)) obj = {50,'X','Y','Z','A','B'}; 

int main ()
{
    struct test *ptr= &obj;
    char *ind = (char *) &obj;

    printf("\nLet's see what is the address of obj %d", ptr);
    printf("\n Size of obj is : %d bytes ", sizeof(obj));
    printf("\nAddress of x is %d", &ptr->x);
    printf("\nAddress of c1 is %d", &ptr->c1);
    printf("\nAddress of c2 is %d", &ptr->c2);
    printf("\nValue  of x is %d", ptr->x);
    printf("\nAddress of x is %c", ptr->c1);
    printf("\nFetching value of c4 through offset %c", *(ind+7));

}
Run Code Online (Sandbox Code Playgroud)

上面的代码按预期工作,大小obj为9个字节(填充为12个字节).

但是,当我int d在我的结构中取消注释时,代码输出:

obj的大小是:16个字节

而不是预期的13(9 + 4)字节.

怎么了?

MiJ*_*iJo 1

在结构中涉及两种类型的填充。(1) 添加填充以使结构成为某个数字的倍数(在您的情况下为 的大小int)和 (2) 添加填充以将某些数据类型放置在可被某个数字整除的地址处。例如,4 个字节int。因此,在您的情况下,虽然编译器很乐意删除第一种填充类型,但我认为它仍然强制成员int d到可被 4 整除的地址。由于之前有 5 个字符d,因此添加 3 个字节填充以强制d到可被 4 整除的地址。

因此,请尝试将成员移动int d到字符上方。那么当然你必须改变 中使用的偏移量fetching value of c4 through offset。您甚至可以将其放在正上方c5。那么你就不必改变你的fetching value of c4 through offset线路了。例子:

struct test {

    int x;
    int d;
    char c1;
    char c2;
    char c3;
    char c4;
    char c5;

} __attribute__((packed)) obj = {50,'X','Y','Z','A','B'}; 
Run Code Online (Sandbox Code Playgroud)

或者

struct test {

    int x;
    char c1;
    char c2;
    char c3;
    char c4;
    int d;
    char c5;

} __attribute__((packed)) obj = {50,'X','Y','Z','A','B'}; 
Run Code Online (Sandbox Code Playgroud)