zoukankan      html  css  js  c++  java
  • C语言结构体对齐

    1.结构体变量中的元素如何访问?

    (1)数组中元素的访问方式:表面上有2种方式(数组下标方式和指针方式);实质上都是指针方式访问。
    (2)结构体变量中的元素访问方式:只有一种,用.或者->的方式来访问。(.和->访问结构体元素其实质是一样的,只是C语言规定用结构体变量来访问元素用. 用结构体变量的指针来访问元素用->。实际上在高级语言中已经不区分了,都用.)
    (3)结构体的访问方式有点类似于数组下标的方式

    2.利用指针访问结构体元素

      结构体元素地址=结构体首地址+元素偏移量

      

    struct mystruct
    {
        int a;            
        int b;            
    
    } s1;
    
    //s1.b的地址
    int* p=(int*)((int)&s1+4);
    *p=5;// s1.b=5;

    3.结构体对齐

      一般情况下,为了配合硬件,如果对齐排布和访问会提高效率,否则会大大降低效率。

      (0)、一般编辑器默认4字节对齐。

      (1)、结构体对齐要考虑:结构体整体本身必须安置在4字节对齐处,结构体对齐后的大小必须4的倍数(编译器设置为4字节对齐时,如果编译器设置为8字节对齐,则这里的4是8)
      (2)、结构体中每个元素本身都必须对其存放,而每个元素本身都有自己的对齐规则。
      (3)、编译器考虑结构体存放时,以满足以上2点要求的最少内存需要的排布来算。

    struct mystruct1
    {                      // 1字节对齐    4字节对齐
        int a;         // 4            4
        char b;              // 1            2(1+1)
        short c;            // 2            2
    }; 
    
    struct mystruct11
    {                     // 1字节对齐    4字节对齐
        int a;            // 4            4
        char b;           // 1            2(1+1)
        short c;         // 2            2
    };
    
    typedef struct mystruct111
    {                    // 1字节对齐    4字节对齐        2字节对齐
        int a;            // 4            4                4
        char b;          // 1            2(1+1)            2
        short c;         // 2            2                2
        short d;         // 2            4(2+2)            2
    } My111;
    
    typedef struct mystruct2
    {                    // 1字节对齐    4字节对齐
        char a;           // 1            4(1+3)
        int b;            // 4            4
        short c;         // 2            4(2+2)
    }MyS2;
    
    struct mystruct21
    {                    // 1字节对齐    4字节对齐
        char a;            // 1           4(1+3)
        int b;            // 4            4
        short c;          // 2            4(2+2)
    } ;
    typedef struct myStruct5
    {                            // 1字节对齐    4字节对齐
        int a;                    // 4          4
        struct mystruct1 s1;    // 7            8
        double b;                // 8           8
        int c;                    // 4          4    
    }MyS5;
    
    struct stu
    {                            // 1字节对齐    4字节对齐
        char sex;                // 1            4(1+3)
        int length;                // 4            4
        char name[10];            // 10            12(10+2)
    };

    4.结构体对齐指令

      以#prgama pack(n)开头,以#pragma pack()结尾,定义一个区间,这个区间内的对齐参数就是n。

    #pragma pack(2)
    
    struct s
    {
        char c;            //2 (1+1)
        int b;             //4 (4)
    
    } ;
    #pragma pack()

      取消对齐访问
      __attribute__((packed));
      设置结构体整体对齐访问(不包含元素)
      __attribute__((aligned(n)));

      

    struct mystruct11
    {                    // 1字节对齐    4字节对齐
        int a;            // 4            4
        char b;            // 1            2(1+1)
        short c;        // 2            2
    }__attribute__((packed));
    
    typedef struct mystruct111
    {                    // 1字节对齐    4字节对齐        2字节对齐
        int a;            // 4            4                4
        char b;            // 1            2(1+1)            2
        short c;        // 2            2                2
        short d;        // 2            4(2+2)            2
    }__attribute__((aligned(1024))) My111;

    5.offsetof宏与container_of宏

    offsetof            在0地址处虚拟出一个结构体,通过元素的地址则为偏移量

    container_of     通过元素地址减去偏移量得到结构体地址

    typeof()传入变量,返回相应的数据类型。
    #include<stdio.h>
    
    struct mystruct
    {
        char a;
        int b;
        short c;
        
    };
    // TYPE是结构体类型,MEMBER是结构体中一个元素的元素名
    // 这个宏返回的是member元素相对于整个结构体变量的首地址的偏移量,类型是int
    #define offsetof(TYPE, MEMBER) ((int) &(((TYPE *)0)->MEMBER))//TYPE *为传入值 
    
     // ptr是指向结构体元素member的指针,type是结构体类型,member是结构体中一个元素的元素名
    // 这个宏返回的就是指向整个结构体变量的指针,类型是(type *)
    //typeof() 是通过变量名 返回数据类型的
    #define container_of(ptr, type, member) ({            
        const typeof(((type *)0)->member) * __mptr = (ptr);      //定义一个typeof(((type *)0)->member)类型的指针指向 结构体元素地址
        (type *)((char *)__mptr - offsetof(type, member)); })  //元素地址-偏移量=结构体首地址
        //通过元素地址减去偏移量得到结构体地址
    int main()
    {
        struct mystruct s1;
        struct mystruct *Ps;
        s1.b=12;
        int * pb=&s1.b;
        Ps=container_of(pb,struct mystruct,b);
        printf("container_of宏实例
    ");
        printf("&s1=%p
    ",&s1);
        printf("Ps=%p
    ",Ps);
        
        
        //int *p=(int *)((char*)&s1+4);
        int *p=(int *)((int)&s1+4);
        printf("*p=%d.
    ",*p);
        printf("offsetof宏实例
    ");
        int offsetof_a=offsetof(struct mystruct,a);
        int offsetof_b=offsetof(struct mystruct,b);
        int offsetof_c=offsetof(struct mystruct,c);
        printf("offsetof_a=%d
    ",offsetof_a);
        printf("offsetof_b=%d
    ",offsetof_b);
        printf("offsetof_c=%d
    ",offsetof_c);
        
        return 0;    
        
    }
  • 相关阅读:
    MySQL 练习题
    MySQL 增删查改
    HTML显示与隐藏
    360布局
    div布局
    HTML练习2
    HTML练习

    if语句的用法及其案例
    输入输出,数据类型与运算符
  • 原文地址:https://www.cnblogs.com/PengfeiSong/p/6257869.html
Copyright © 2011-2022 走看看