• C语言学习笔记_结构体的内存对齐


    C语言学习笔记_结构体的内存对齐

    结构体的指针访问和下标访问

    结构体可以在定义的同时申明变量:

    // 定义的同时申明变量s1;
    struct student {
    	int a;
    	double b;
        char c;
    }s1 ;
    // 申明s2;
    struct student s2;
    

    结构体的下标访问:

    s1.a = 1;
    s1.b = 2.2;
    s1.c = 'x';
    
    printf("s1.a = %d.
    ", s1.a);
    printf("s1.a = %f.
    ", s1.b;
    printf("s1.a = %c.
    ", s1.c);
    

    结构体的指针访问:

    // 第一个变量在开始,所以直接转换结构体的地址为int *;
    int *p = (int *)&s1; 
    *p = 12;
    printf("s1.a = %d.
    ", s1.a);
    
    // 经过第一个变量到达第二个变量的首地址,第一个变量为int,所以转换为int类型在加4,得到真正的地址;
    double *d = (double *)((int)&s1+4); 
    *d = 3.3;
    printf("s1.a = %f.
    ", s1.b;
    
    // 和上一个相同,不过double类型的长度为8,所以地址相差4+8=12;    
    char *c = (char *)((int)&s1+12);
    *c = 'y';
    printf("s1.a = %c.
    ", s1.c);
    

    可以发现结构体的指针访问可以更好的理解结构体的对齐访问;

    结构体的对齐访问

    结构体中的数据类型长短不一,数据的对齐访问方式牺牲部分内存以提高访问效率,;

    在32位系统中采用4字节对齐,有以下特点:

    1. 结构体本身必须在4字节对齐处;
    2. 结构体对齐后的大小必须是4的倍数,N字节对齐则为N的整数倍;
    3. 结构体中每个元素必须对齐存放,每个元素有自身的对齐规则;
    4. 编译器考虑结构体存放时,以满足以上规则的最少内存消耗策略;

    下面是一些对齐访问的案例

    struct s1 {         // 无对齐     4字节对齐
    	int a;          // 4         4		  
    	char b;         // 1         2(1+1)
    	short c;        // 2         2
    };                  
    sizeof(struct s1);  // 7         8
    
    struct s2 {         // 无对齐     4字节对齐
        char a;         // 1         4(1+3)
        int b;          // 4         4
        short c;        // 2         4(2+2)
    };                  
    sizeof(struct s2);  // 7         12
    
    struct s3 {         // 无对齐     4字节对齐
        int a;          // 4         4
        struct s1 s;    // 7         8
        double b;       // 8         8
        int c;          // 4         4
    };                  
    sizeof(struct s3);  // 23        24
    
    struct student{     // 无对齐     4字节对齐
        char sex;       // 1         4(1+3)
        int length;     // 4         4
        char name[10];  // 10        12(10+2)
    };                  
    sizeof(struct student);// 15        20 
    

    gcc的对齐指令

    gcc支持但不推荐的对齐指令:

    通过pramaga指令和参数k设置一个区间,此区间内为k字节对齐:

    // 设置对齐字节为1字节,相当于不对齐
    #pragma pack(1)
    struct s1 {         
    	int a;          	  
    	char b;         
    	short c;        
    };                  
    // 长度为7
    printf("sizeof(struct s1) = %d.
    ", sizeof(struct s1)); 
    
    // 结束
    #pragma pack
    

    gcc支持且推荐的对齐指令:

    在声明结构体的后面加上该指令,只作用于此类型;

    //  __attribute__((packed))表示取消对齐,只作用于s1;
    struct s1 {         
    	int a;          	  
    	char b;         
    	short c;        
    } __attribute__((packed)); 
    
    // __attribute__((aligned(n)))表示结构体设置整体n个字节对齐,这里设置4字节对齐,只作用于s2;
    struct s2 {         
    	int a;          	  
    	char b;         
    	short c;        
    } __attribute__((aligned(4))); 
    

    注意这里的aligned是整体n字节对齐,和前面的对齐以及prama的对齐不一样,前面的对齐是结构体中每个元素按照n字节对齐,而aligned中结构体的元素还是4字节对齐,整体按照n字节对齐;

  • 相关阅读:
    php跨平台总结 常用预定义常量
    HDU 2065 "红色病毒"问题 (指数母函数 && 泰勒级数)
    ZOJ 3662 Math Magic (2012 Changchun Regional; LCM,DP)
    HDU 2065 "红色病毒"问题 (指数母函数 && 泰勒级数)
    状态压缩DP棋盘模型总结
    HDU 3033 I love sneakers! (分组背包变形)
    状态压缩DP棋盘模型总结
    ZOJ 3662 Math Magic (2012 Changchun Regional; LCM,DP)
    POJ 2671 Jimmy's Bad Day ★ (区间DP)
    HDU 3033 I love sneakers! (分组背包变形)
  • 原文地址:https://www.cnblogs.com/sakurapiggy/p/13200130.html
Copyright © 2020-2023  润新知