C语言结构体,内存对齐

本文探讨了C语言中结构体内存对齐的重要性,解释了内存对齐的必要性和方法,包括默认规则和自定义对齐值。通过实例展示了不同变量顺序和对齐设置对内存占用的影响,并介绍了位域的使用,强调了位域在内存对齐中的特殊性。通过联合使用位域,可以节省内存空间并优化内存访问。
摘要由CSDN通过智能技术生成

1、为什么要内存对齐

许多计算机系统对基本数据类型的合法地址做出了一些限制,要求某种类型对象的地址必须是某个值K(通常是2,4,8,或16)的倍数。这种对齐限制简化了形成处理器和内存系统之间接口的硬件设计。(来源于计算机操作系统第一部分,程序结构和执行)
其中详细解释参考大神博客
https://blog.csdn.net/lgouc/article/details/8235471

2、内存对齐方法

1、利用默认规则
例1:

//代码1  共占用 2 * sizeof(int) 个字节
struct  test
{
    char a;
    char b;
    int num;
}

代码1 变量内存分布如图
默认情况下以 int 型变量 的字节数(K值)进行对齐。
在这里插入图片描述因为char 类型只占用了一个字节,所以占1格,int 型需要4个字节,占了4格
所以整个test 结构体需要8个字节。

例2:

//代码2   共占用 3 * sizeof(int) 个字节
struct  test
{
    char a;
    int num;
    char b;
    
}

代码2 变量内存分布如图
在这里插入图片描述

总结:
在使用gcc编译时,由于结构体内变量按照先后顺序在内存中存储,且按照默认规则以4进行对齐。要求结构体起始地址必须是4的倍数。在存储char 类型后,存储int 类型时仍然要求起始地址为4的倍数,所以char 类型后的地址就不满足存储要求。所以char 类型后空了3个字节。所以这就是代码2的内存分布原因。
代码1的在存储char类型后,下一个还是char类型。只有一个字节,所以第一个char 类型后的地址是满足存储要求的。所以分布如代码1下的图示所示。

实例展示

类似的代码和实际运算结果展示:

#include <stdio.h>

struct ffe
{
    char a;    //占用4个字节 实际使用1个字节
    int b;     //占用4个字节 实际使用4个字节 ,和char 变量共用8个字节
    double c;  //占用8个字节 实际使用8个字节
};

int main()
{
    ffe tr;
    printf("%d\n",sizeof(tr));
    printf("a = %p\n, b = %p\n, c = %p\n",&tr.a, &tr.b, &tr.c);

    return 0;
}

输出结果:

16 a = 0x7ffcbf14ca00 , b =0x7ffcbf14ca04, c = 0x7ffcbf14ca08

内存中分布大概如图示
在这里插入图片描述
当变量位置交换后,实际占用内存为 3 * sizeof(double)。 一般为24字节。

struct ffe
{
    char a;    //占用8个字节,实际使用1个字节
    double c;   //占用8个字节,实际使用8个字节
    int b;    //占用8个字节,实际使用4个字节
};   

所以根据变量字节大小来决定变量顺序可以有效减小使用内存。

2、设置结构体内存对齐K
使用如下语句
#pragma pack(k) //没有分号
对应代码1,如果将k 设置为1,则实际内存占用为6个字节。将K设置为2 ,结果也是一致的。因为设置了变量的变量的对齐为2的倍数。但整型变量实际占用了两个内存单元。会造成取值速度下降。
在这里插入图片描述
K = 4 的结果与代码1的结果是一致的。
当K = 8 超过了默认的 K =4 (int 4个字节)。内存对齐仍然是按照 K = 4 进行内存对齐的。

3.位域

位域:描述的是结构体中变量占的位。(一个字节共有8个位)
char 类型,一个字节 ,共有8个位,所以位域数不能超过8。
int 类型 ,4个字节,共有32个位,所以位域数不能超过32。

具体使用

//代码3
struct ffe
{
    char a:2;
    char b:2;
    char c:2; 
};

由于一个字节(8个位)是系统中最小可寻址单位。所以无法对位域取地址。无法通过地址查看相关关系。

代码3的结构体,占用内存为一个字节。由于一个字符变量只使用了两个位,表示的最大字符ASCII码不能超过3;因为超过了就会溢出。

但是变量仍然满足内存对齐规则。代码4的结构体仍然占据8个字节。

//代码4
struct ffe
{
    char a:2;
    char b:2;
    char c:2; 
    int d:1;
};

只能通过大小或者赋值去判断。

4、位域的联合使用

struct ttr
{
    int a:8;
    int b:8;
    int c:8;
    int d:8;
};

union ffe
{
    int a;
    ttr ch;
};

整型变量a 和结构体变量ch 共同占据同一块内存,两种类型的内存大小是一致的,地址是一致的。访问变量按照正常访问即可,所以可以通过两种类型访问同一块内存 。将较小的值限制在相应的小空间内。达到节约内存的目的。所以赋值不能超过实际的位。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值