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.\n", s1.a);
printf("s1.a = %f.\n", s1.b;
printf("s1.a = %c.\n", s1.c);

结构体的指针访问:

// 第一个变量在开始,所以直接转换结构体的地址为int *;
int *p = (int *)&s1; 
*p = 12;
printf("s1.a = %d.\n", s1.a);

// 经过第一个变量到达第二个变量的首地址,第一个变量为int,所以转换为int类型在加4,得到真正的地址;
double *d = (double *)((int)&s1+4); 
*d = 3.3;
printf("s1.a = %f.\n", s1.b;

// 和上一个相同,不过double类型的长度为8,所以地址相差4+8=12;    
char *c = (char *)((int)&s1+12);
*c = 'y';
printf("s1.a = %c.\n", 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.\n", 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字节对齐;

posted @ 2020-06-27 21:54  樱花小猪  阅读(190)  评论(0编辑  收藏  举报