栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

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

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

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

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

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

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

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

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

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

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

#include 
int main()
{
	printf("int=%dn", sizeof(int));
	printf("short=%dn", sizeof(short));
	printf("char=%dn", sizeof(char));
	printf("float=%dn", sizeof(float));
	printf("double=%dn", sizeof(double));
	printf("int *=%dn", sizeof(int*));
	printf("char *=%dn", sizeof(char*));
	printf("float *=%dn", sizeof(float*));
	printf("double *%dn", sizeof(double*));
	return 0;
}

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

必须保证结构体字节对齐(两个对齐)。 (1)保证最长字节对齐 (2)保证整数倍地址对齐 例1
#include 
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 
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 
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 
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 
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 
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 
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 
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个字节。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1037267.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号