0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

关于C语言结构体内存对齐

Q4MP_gh_c472c21 来源:嵌入式大杂烩 作者:嵌入式大杂烩 2022-04-14 12:51 次阅读

今天给大家带来一道经典、易错的关于C语言结构体内存对齐的题目:

32bit环境下以下结构体所占的字节数:
typedefstructtest_struct
{
chara;
shortb;
charc;
intd;
chare;
}test_struct;

请说出你的答案:

下面看一下实际测试情况:

1、测试代码:

/***********************************
*公众号:嵌入式大杂烩
***********************************/
#include

typedefstructtest_struct
{
chara;
shortb;
charc;
intd;
chare;
}test_struct;

intmain(void)
{
test_structtest_s;

printf("
============================================
");
printf("test_saddr=%#.8x
",&test_s);
printf("test_s.aaddr=%#.8x
",&test_s.a);
printf("test_s.baddr=%#.8x
",&test_s.b);
printf("test_s.caddr=%#.8x
",&test_s.c);
printf("test_s.daddr=%#.8x
",&test_s.d);
printf("test_s.eaddr=%#.8x
",&test_s.e);
printf("sizeof(test_s)=%d
",sizeof(test_s));
printf("============================================
");

return0;
}

2、运行结果

关于C语言结构体内存对齐

在32bit环境中,该结构体所占的字节数为16。答对了吗?

运行结果打印输出了很多重要的信息,从结果往前分析思路应该很清晰了吧?

下面,我们一起来分析分析。

3、分析

在分析这个问题之前,我们先记住关于结构体内存对齐的三条原则:

(1)结构体变量的起始地址能够被其最宽的成员大小整除。

(2)结构体每个成员相对于起始地址的偏移能够被其自身大小整除,如果不能则在前一个成员后面补充字节

(3)结构体总体大小能够被最宽的成员的大小整除,如不能则在后面补充字节

分析这个问题我们就不考虑编译器可以指定对齐大小的情况了。在32bit环境中,一般默认的对齐大小是4。

下面,我们根据这三条原则来分析,并得出如下示意图:

关于C语言结构体内存对齐

从这张图中,我们应该可以很清晰地看出整个结构体变量的内存占用情况。

如果还看不明白的朋友,可以阅读下面的解释(有点啰嗦,已经看明白的就不用看了~):

从上例的结果中,我们结构体变量test_s的起始地址为0x0028ff30,能够被其最宽的成员(int类型的d成员,占4个字节)整除,符合第(1)条原则。

a成员的地址即为结构体变量的起始地址0x0028ff30,排在a后面的是short类型(两个字节)的b成员。

根据第(2)条规则,显然b的地址不能从0x0028ff31开始,则编译器会在b成员的前一个成员(a成员)后边补1个空白字节,即b的的地址为从0x0028ff32,符合规则(2)。

b成员占两个字节,两个字节之后的地址为0x0028ff34,而c成员为char类型(1字节),则根据规则(2),c成员会存放至地址0x0028ff34处。

c成员占1个字节,1个字节之后的地址为0x0028ff35,排在c后面的是int类型(4个字节)的d成员,显然不能满足规则(2)。

编译器会在d成员的前一个成员(c成员)后面进行字节填充,这里必须填充3个字节才能符合规则(2),此时d会存放至地址0x0028ff38处。

d成员占4个字节,4个字节之后的地址为0x0028ff3c。根据规则(2),e成员可从该地址开始存放。

此时a+空白字节+b+c+空白字节+d+e所占的字节总数为13个字节,而结构体最宽的成员(int类型的d成员)所占字节数为4字节。

显然不能满足规则(3),编译器会在e成员后面填充3个字节。即整个结构体变量test_s所占的总字节数为16字节。

4、实际应用

(1)用保留变量替代填充字节

实际应用中,我们可以上面的结构体变量改为:

typedefstructtest_struct
{
chara;
charreserve0;/*保留成员*/
shortb;
charc;
intd;
chare;
charreserve1[3];/*保留成员*/
}test_struct;

我们已经知道了编译器会自动给我们的结构体变量填充一些空白字节,这些填充字节我们是看不到的,是隐性的。

在结构体变量占用相同内存的情况下,我们可以显性的表示出这些填充字节,即创建一些保留成员。

这样,当我们需要给这个结构体添加一些成员时,我们可以把保留的成员替换为实际的成员。这样在一定程度下有利于我们节省内存空间。

(2)调整结构体成员的位置

从上面的分析中,我们知道编译器会根据我们结构体成员的排列来进行空白字节填充以达到对齐的效果。

那么,我们自己进行手动对齐一些成员,那就可以节省一些空间了。比如把上面的我们的test_struct结构体成员的顺序改为:

typedefstructtest_struct
{
chara;
charc;
shortb;
intd;
chare;
}test_struct;

则结构体变量test_s所占的字节数变为12字节,即:

关于C语言结构体内存对齐

即比原来的16字节省下了4个字节。

虽然这点优化对于一般的嵌入式应用来说可能没什么必要,但是万一某一天真的需要在某些资源极其受限的嵌入式设备中开发应用,这就是可以优化的一点。

最后

以上就是本次的实验分享。如有错误,欢迎指出!谢谢

这道结构体内存对齐的题目很经典、也很容易出错,是嵌入式C语言笔试、面试题中的高频题目,很有必要弄清楚。

原文标题:嵌入式C结构体内存对齐

文章出处:【微信公众号:嵌入式ARM】欢迎添加关注!文章转载请注明出处。

审核编辑:汤梓红
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 内存
    +关注

    关注

    8

    文章

    2762

    浏览量

    72742
  • C语言
    +关注

    关注

    180

    文章

    7527

    浏览量

    128178
  • 结构体
    +关注

    关注

    1

    文章

    125

    浏览量

    10749

原文标题:嵌入式C结构体内存对齐

文章出处:【微信号:gh_c472c2199c88,微信公众号:嵌入式微处理器】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    关于C语言结构体内存对齐

    今天给大家带来一道经典、易错的关于C语言结构体内存对齐的题目。
    发表于 09-08 11:54 372次阅读

    C语言结构对齐介绍

    大家好,我是嵌入式老林,从事嵌入式软件开发多年,今天分享的内容是C语言结构对齐介绍,希望能对你有所帮助
    发表于 07-11 11:50 603次阅读
    C<b class='flag-5'>语言</b><b class='flag-5'>结构</b>体<b class='flag-5'>对齐</b>介绍

    C语言零基础教程之结构体内存对齐,手把手带你轻松上手C语言

    C语言编程语言
    电子学习
    发布于 :2023年01月14日 13:22:17

    C语言-结构对齐详解

    `C语言-结构对齐详解朱有鹏1、结构体为何要对齐访问访问
    发表于 07-12 16:41

    C语言内存对齐

    16B. 12 12C. 16 24D.16 20我觉得应该选C。在class B中,a占了8byte,b占了2byte,c占了4byte,d占了1byte,因为这是64位机器,考虑到对齐
    发表于 10-13 17:35

    漫谈C语言结构

    我放在下面。  在此,我会围绕以下2个问题来分析和应用C语言结构体:  1. C语言中的结构体有
    发表于 11-15 15:59

    【原创】在嵌入式系统中大小端和对齐问题

    作者:黄忠老师(张飞实战电子高级工程师)C语言是一种高级语言,在大多数情况下C语言的代码是和具体的处理器体系
    发表于 07-30 09:34

    结构体变量的定义与使用变量访问结构体成员

    知识点回顾关于找最大公共子串的两种解题方法结构体的定义(3种)结构体变量的定义与使用变量访问结构体成员 .指针访问结构体成员 ->
    发表于 12-17 07:10

    掌握在单片机下使用C语言编程内存对齐的知识点

    一、前言在单片机下使用C语言编程时,内存对齐的知识点必须掌握。掌握内存对齐后,可以防止
    发表于 02-28 07:47

    了解内存:如何在嵌入式C语言中使用结构

    处理器如何访问内存?了解有关C语言结构以及如何使用它们的更多信息。 本文将首先解释内存访问粒度的概念,以便我们可以对处理器如何访问内存有一个
    的头像 发表于 09-28 09:46 1404次阅读

    解析C语言结构体字节如何对齐

    01 默认字节对齐 C语言结构体字节对齐是老生常谈的问题了,也是高频面试题,现在我们来深入研究这个问题,彻底弄懂到底是怎么回事,给你一个结构
    的头像 发表于 06-12 17:42 2819次阅读

    C语言中Linux字节对齐的问题

    ,于是经过排查,是因为传递消息的结构体没有考虑字节对齐的问题。 随手整理一下C语言中字节对齐的问题与大家一起分享。 一、概念 对齐跟数据在
    的头像 发表于 08-16 11:25 2170次阅读
    C<b class='flag-5'>语言</b>中Linux字节<b class='flag-5'>对齐</b>的问题

    C语言 | 内存对齐01 - 什么是内存对齐

    一、前言在单片机下使用C语言编程时,内存对齐的知识点必须掌握。掌握内存对齐后,可以防止内存碎片化
    发表于 01-13 15:18 0次下载
    C<b class='flag-5'>语言</b> | <b class='flag-5'>内存</b><b class='flag-5'>对齐</b>01 - 什么是<b class='flag-5'>内存</b><b class='flag-5'>对齐</b>

    为什么要结构对齐?为什么结构对齐那么重要?

    C语言结构对齐问题,是面试必备问题。我参与招聘技术面试的时候,也喜欢问这个技术点。
    的头像 发表于 05-26 14:10 661次阅读
    为什么要<b class='flag-5'>结构</b>体<b class='flag-5'>对齐</b>?为什么<b class='flag-5'>结构</b>体<b class='flag-5'>对齐</b>那么重要?

    keil arm工程中结构体1字节对齐如何实现

    在Keil Arm工程中,结构体的对齐方式可以通过使用特定的编译器指令或者关键字来实现。结构体的对齐方式会直接影响结构体变量在
    的头像 发表于 01-05 14:40 1098次阅读