7

C | 结构体字节对齐 - 就良同学

 1 year ago
source link: https://www.cnblogs.com/lijiuliang/p/17232542.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

01.字节对齐现象

#include<stdio.h>

struct st1{
    char a;
    short b;
    int c;
};
struct st2{
    char a;
	int c;
    short b;
};

int main(){
	printf("sizeof st1 = %u\n", sizeof(struct st1));
	printf("sizeof st2 = %u\n", sizeof(struct st2));
	return 0;
}
sizeof st1 = 8
sizeof st2 = 12

st1和st2的成员变量均为一个char变量、一个int变量、一个short变量,区别在于二者的成员变量顺序不同。

但是st1和st2两结构体所占内存大小却不一致,这一奇怪的现象底层就是因为C语言结构体发生了字节对齐。

02.为什么要字节对齐——以空间换时间

内存的最小单元是一个字节,理论上当cpu从内存中读取数据时,应该是逐字节读取。但是实际上cpu将内存当成了多个块,这个块的大小可能是2、4、8、16等。字节对齐是操作系统为了提高内存访问效率的策略。如果没有对齐,就会有可能出现为了访问一个变量却进行了多次内存访问的情形。

2.1 字节对齐原理

1)变量地址规则

#include<stdio.h>

int main(){
	char c1, c2, c3;
	short s1, s2, s3;
	int i1, i2, i3;
	double d1, d2, d3;

	printf("char:\t%lld %lld %lld\n", &c1, &c2, &c3);
	printf("short:\t%lld %lld %lld\n", &s1, &s2, &s3);
	printf("int:\t%lld %lld %lld\n", &i1, &i2, &i3);
	printf("double:\t%lld %lld %lld\n", &d1, &d2, &d3);
	return 0;
}
char:   1703724 1703720 1703716
short:  1703712 1703708 1703704
int:    1703700 1703696 1703692
double: 1703684 1703676 1703668

发现现象:

同一类型下,其每个变量的地址一定可以被该类型所占内存大小(字节为单位)整除。如(64位操作系统下):

  • char中的1703724 、1703720 、1703716均能被1整除(char占1个字节);
  • short中的1703712 、1703708 、1703704均能被2整除(short占2个字节);
  • int中的1703700 、1703696 、1703692均能被4整除(int占4个字节);
  • double中的1703684 、1703676 、1703668均能被8整除(double占8个字节)。

2)结构体字节对齐

  • 结构体中每个成员变量,其变量地址须满足该地址能够被该类型所占内存大小(字节为单位)整除(即地址是该类型长度的整数倍),如不满足,则填充字节直至当前地址满足此条件。

  • 结构体的总大小须为其最大成员大小的整数倍,如不满足,最后填充字节以满足。

image

理解请参考:

03.结构体嵌套结构体进行字节对齐

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

struct sa{
    int a;  //0-3
    char b; //4
    double c;   //8-15
};

struct sb{
    char a; //0
    struct sa b;    //8-23 
    double c;   // 24-31
};

int main(){
    printf("sizeof(struct sa):%u\n", sizeof(struct sa));
    printf("sizeof(struct sb):%u\n", sizeof(struct sb));
    return 0;
}
sizeof(struct sa):16
sizeof(struct sb):32

struct sb中的字段b,是以其内部的最大变量类型位基准(即double),而不是以sturct sa结构体的大小位基准。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK