C语言中关于结构体字节对齐问题和定义原则-内存分配

本文通过多个实例详细解析了C语言中结构体的内存分配原则,包括最长字节对齐和整数倍地址对齐,展示了如何合理布局结构体成员以减少内存浪费。

1、首先我们要知道一些变量所占据的内存有多少和字节的换算单位。

(1)1B(字节)= 8位(比特)

(2)1KB(千字节)= 1024(2^9)B(字节)

(3)1MB(兆字节)= 1024KB(千字节)

(4)1GB(吉字节)= 1024MB(兆字节)

(5)1TB(太字节) = 1024GB(吉字节)

2、C语言中变量所占据的内存。

#include <stdio.h>
int main()
{
	printf("int=%d\n", sizeof(int));
	printf("short=%d\n", sizeof(short));
	printf("char=%d\n", sizeof(char));
	printf("float=%d\n", sizeof(float));
	printf("double=%d\n", sizeof(double));
	printf("int *=%d\n", sizeof(int*));
	printf("char *=%d\n", sizeof(char*));
	printf("float *=%d\n", sizeof(float*));
	printf("double *%d\n", sizeof(double*));
	return 0;
}

我们知道每个变量和它所占的内存后,我们就可以更好的去定义结构体了,首先明确结构体定义的原则:

必须保证结构体字节对齐(两个对齐)。

(1)保证最长字节对齐

(2)保证整数倍地址对齐

例1

#include <stdio.h>
int main()
{
	typedef struct Student 
	{
		int a;
		char c;
}Student;
	printf("%d", sizeof(Student));
	return 0;
}

        如果你不了解结构体的内存分配,你大概率会猜此结构体占内存为5个字节,正确答案:输出结果为8字节,一个整型加一个字符型变量,正常运算的确是5个字节,但是在结构体中存储方式是不同的,如图,在地址空间中a和c是并列的,结构体中也是挨着的,原则中,必须保证最长字节对齐,所以有3个字节是被浪费掉的,总体占据8个字节。

a
cxxx

 例2

#include <stdio.h>
int main()
{
	typedef struct Student 
	{
		char a;
		int b;
		char c;
}Student;
	printf("%d", sizeof(Student));
	return 0;
}

一个字符型,两个整型变量,在结构体中要保证最长字节对齐,所以此结构体输出为12字节,空间内存分配如图

axxx
b
cxxx

如图,最长字节对齐,所以每个变量占据4个字节,但是有6字节的空间是被浪费掉的,b的地址在a的后面,c的地址在b的后面,地址是从小到大排列的。

例2改进

#include <stdio.h>
int main()
{
	typedef struct Student 
	{
		int a;
		char b;
		char c;
}Student;
	printf("%d", sizeof(Student));
	return 0;
}

如图,输出结果为8字节,三个变量和例1的两个变量内存空间占据相同,空间中内存分配如图:

a
bcxx

最开始的原则中第二条我们说过保证整数倍地址对齐,最后两个字节被浪费,存储的8个位置我们给它地址进行编号,如图储存的变量位置必须是内存的整数倍,也就是说,如果两个占4字节的变量存储,那么都会被占满,或者是四个占2字节的变量,可以完全占用。

0123
4567

 例3

#include <stdio.h>
int main()
{
	typedef struct Student {
		int a;
		short b;
		char c;
		char d;
	}Student;
	printf("%d", sizeof(Student));
	return 0;
}

结构体中是定义了一个整型,一个短整型,两个字符型变量,以最长的int为标准,可以知道,地址空间中内存长度为4,整体占据内存为8字节。如图:内存没有被浪费。

a
bcc

例4

#include <stdio.h>
int main()
{
	typedef struct Student {
		int a;
		char b;
		short c;
		char d;
	}Student;
	printf("%d", sizeof(Student));
	return 0;
}

结构体中定义了一个整型,一个短整型,两个字符型变量,定义的数量相同,但是因为地址空间的位置不同,它所占据的内存也不是和例3一样的8字节,它是12字节。如图:

a
bxc
dxxx

 最长的整型变量a占据4个字节,按照原则2,保证整数倍地址对齐c占两个字节,所以c的位置应该是2的整数倍如果对其进行编号,c的起始地址在6位置,d的位置在c后面,以此类推。

0123
4567

 例5

#include <stdio.h>
int main()
{
	typedef struct Student {
		int a;
		long long int  b;
		short c;
		int d;
		char e;
	}Student;
	printf("%d", sizeof(Student));
	return 0;
}

long long int 占据内存为8,计算此结构体所占内存为32字节,可以看到,每一行的地址空间最多8字节,第一行a,b地址在a后面,但是占据8个字节,所以第二行b,占据整行,然后第三行c占据2字节,2字节后面,是d占据4字节,最后一行e占1字节,空了七个字节。如图:

axxxx
    b   
cxxd
exxxxxxx

 那么,如何分配才能让它更好利用内存呢?内存为24字节。

    a   
bc
cexxxxx

 程序如下:

#include <stdio.h>
int main()
{
	typedef struct Student {
		long long int  a;
		int b;
		int c;
		short d;
		char e;
	}Student;
	printf("%d", sizeof(Student));
	return 0;
}

例6

#include <stdio.h>
int main()
{
	typedef struct Student {
		char a : 2;
		char b : 2;
		char c : 2;
		char d : 2;
	}Student;
	printf("%d", sizeof(Student));
	return 0;
}

我们定义了4个字符型变量但是这种表示方法,是在硬件编程中常用的,尤其汇编语言中,这四个变量总计占1个字节,8位(看本文开头),a : 2 定义的是两位,占两个比特。

abcd

 字符型变量2字节,16位,本结构体中总计1个字节。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值