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

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

3天内不再提示

C/C++编译器的缺省字节对齐方式

CHANBAEK 来源:明解嵌入式 作者:Sharemaker001 2023-04-15 11:24 次阅读

C/C++编译器的缺省字节对齐方式为自然对界。 即在缺省情况下,编译器为每一个变量或是数据单元按其自然对界条件分配空间。

在结构中,编译器为结构的每个成员按其自然对界(alignment)条件分配空间。 各个成员按照它们被声明的顺序在内存中顺序存储(成员之间可能有插入的空字节),第一个成员的地址和整个结构的地址相同。

编译器缺省的结构成员自然对界条件为“N字节对齐”,N即该成员数据类型的长度。 如int型成员的自然对界条件为4字节对齐,而double类型的结构成员的自然对界条件为8字节对齐。 若该成员的起始偏移不位于该成员的“默认自然对界条件”上,则在前一个节面后面添加适当个数的空字节。

编译器缺省的结构整体的自然对界条件为:该结构所有成员中要求的最大自然对界条件。 若结构体各成员长度之和不为“结构整体自然对界条件的整数倍”,则在最后一个成员后填充空字节。

例子1(分析结构各成员的默认字节对界条界条件和结构整体的默认字节对界条件):

struct Test
{ 
  char x1; // 成员x1为char型(其起始地址必须1字节对界),其偏移地址为0 
  char x2; // 成员x2为char型(其起始地址必须1字节对界,其偏移地址为1 
  float x3; // 成员x3为float型(其起始地址必须4字节对界),编译器在x2和x3之间填充了两个空字节,其偏移地址为4 
  char x4; // 成员x4为char型(其起始地址必须1字节对界),其偏移地址为8 
};

在Test结构体中,最大的成员为float x3,因此结构体的自然对界条件为4字节对齐。 则结构体长度就为12字节,内存布局为1100 1111 1000。

例子2:

#include 
typedef struct
{
  int aa1; //4个字节对齐 1111
  char bb1;//1个字节对齐 1
  short cc1;//2个字节对齐 011
  char dd1; //1个字节对齐 1
} testlength1;
int length1 = sizeof(testlength1); //4个字节对齐,占用字节1111 1011 1000,length = 12


typedef struct
{
  char bb2;//1个字节对齐 1
  int aa2; //4个字节对齐 01111
  short cc2;//2个字节对齐 11
  char dd2; //1个字节对齐 1
} testlength2;
int length2 = sizeof(testlength2); //4个字节对齐,占用字节1011  1111 1000,length = 12


typedef struct
{
  char bb3; //1个字节对齐 1
  char dd3; //1个字节对齐 1
  int aa3; //4个字节对齐 001111
  short cc23//2个字节对齐 11


} testlength3;
int length3 = sizeof(testlength3); //4个字节对齐,占用字节1100 1111 1100,length = 12


typedef struct
{
  char bb4; //1个字节对齐 1
  char dd4; //1个字节对齐 1
  short cc4;//2个字节对齐 11
  int aa4; //4个字节对齐 1111
} testlength4;
int length4 = sizeof(testlength4); //4个字节对齐,占用字节1111 1111,length = 8


int main(void)
{
  printf("length1 = %d.\\n",length1);
  printf("length2 = %d.\\n",length2);
  printf("length3 = %d.\\n",length3);
  printf("length4 = %d.\\n",length4);
  return 0;
}

改变缺省的对界条件(指定对界)

· 使用伪指令#pragma pack (n),编译器将按照n个字节对齐。
· 使用伪指令#pragma pack (),取消自定义字节对齐方式。

这时,对齐规则为:

1、数据成员对齐规则:结构(struct)(或联合(union))的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员的对齐按照#pragma pack指定的数值和这个数据成员自身长度中,比较小的那个进行。

2、结构(或联合)的整体对齐规则:在数据成员完成各自对齐之后,结构(或联合)本身也要进行对齐,对齐将按照#pragma pack指定的数值和结构(或联合)最大数据成员长度中,比较小的那个进行。

结合1、2推断:当#pragma pack的n值等于或超过所有数据成员长度的时候,这个n值的大小将不产生任何效果。

因此,当使用伪指令#pragma pack (2)时,Test结构体的大小为8,内存布局为11 11 11 10。

需要注意一点,当结构体中包含一个子结构体时,子结构中的成员按照#pragma pack指定的数值和子结构最大数据成员长度中,比较小的那个进行进行对齐。 例子如下:

#pragma pack(8)
struct s1
{
  short a;
  long b;
};


struct s2
{
  char c;
  s1 d;
  long long e;
};
#pragma pack()

sizeof(s2)的结果为24。 S1的内存布局为1100 1111,S2的内存布局为1000 1100 1111 0000 1111 1111。

例子2按照2个字节对齐时:

#include 
#pragma pack(2)
typedef struct
{
  int aa1; //2个字节对齐 1111
  char bb1;//1个字节对齐 1
  short cc1;//2个字节对齐 011
  char dd1; //1个字节对齐 1
} testlength1;
int length1 = sizeof(testlength1); //2个字节对齐,占用字节11 11 10 11 10,length = 10


typedef struct
{
  char bb2;//1个字节对齐 1
  int aa2; //2个字节对齐 01111
  short cc2;//2个字节对齐 11
  char dd2; //1个字节对齐 1
} testlength2;
int length2 = sizeof(testlength2); //2个字节对齐,占用字节10 11 11 11 10,length = 10


typedef struct
{
  char bb3; //1个字节对齐 1
  char dd3; //1个字节对齐 1
  int aa3; //2个字节对齐 11 11
  short cc23//2个字节对齐 11


} testlength3;
int length3 = sizeof(testlength3); //2个字节对齐,占用字节11 11 11 11,length = 8


typedef struct
{
  char bb4; //1个字节对齐 1
  char dd4; //1个字节对齐 1
  short cc4;//2个字节对齐 11
  int aa4; //2个字节对齐 11 11
} testlength4;
int length4 = sizeof(testlength4); //2个字节对齐,占用字节11 11 11 11,length = 8
#pragma pack()
int main(void)
{
  printf("length1 = %d.\\n",length1);
  printf("length2 = %d.\\n",length2);
  printf("length3 = %d.\\n",length3);
  printf("length4 = %d.\\n",length4);
  return 0;
}

另外,还有如下的一种方式:

· __attribute((aligned (n))),让所作用的结构成员对齐在n字节自然边界上。 如果结构中有成员的长度大于n,则按照最大成员的长度来对齐。

· attribute ((packed)),取消结构在编译过程中的优化对齐,按照实际占用字节数进行对齐。

以上的n = 1, 2, 4, 8, 16... 第一种方式较为常见。

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

    关注

    13

    文章

    4283

    浏览量

    85739
  • C++
    C++
    +关注

    关注

    22

    文章

    2106

    浏览量

    73560
  • 编译器
    +关注

    关注

    1

    文章

    1619

    浏览量

    49083
  • 变量
    +关注

    关注

    0

    文章

    613

    浏览量

    28351
  • 字节对齐
    +关注

    关注

    0

    文章

    5

    浏览量

    1511
收藏 人收藏

    评论

    相关推荐

    c语言中的字节对齐

    缺省情况下,C编译器为每一个变量或是数据单元按其自然对界条件分配空间。
    的头像 发表于 12-30 11:03 2624次阅读
    <b class='flag-5'>c</b>语言中的<b class='flag-5'>字节</b><b class='flag-5'>对齐</b>

    解决单片机开发字节对齐问题的方法

    单片机开发重点-字节对齐问题在缺省情况下,C编译器为每一个变量或是数据单元按其自然对界条件分配空间。一般地,可以通过下面的方法来改变
    发表于 11-22 06:06

    C++编译器数值性能比较

    现在市面上,主流的C/C++编译器包括M$的CL、gcc、Intel的icl、PGI的pgcc及Codegear的bcc(原来属于Borland公司)。Windows上使用最多的自然是cl,而在更广阔的平台上,gcc则是
    发表于 09-10 11:54 8次下载

    Linux下C/C++编译器gcc使用指南

    1.gcc包含的c/c++编译器 gcc,cc与c++,g++ gcc和cc是一样的,c++和g++是一样的。一般
    发表于 11-02 10:59 0次下载

    MATLAB 64位C语言和C++编译器应用程序免费下载

    本文档的主要内容详细介绍的是MATLAB 64位C语言和C++编译器应用程序免费下载。
    发表于 05-21 08:00 4次下载
    MATLAB 64位<b class='flag-5'>C</b>语言和<b class='flag-5'>C++</b><b class='flag-5'>编译器</b>应用程序免费下载

    阿里云基础软件C/C++编译器的工作现状及挑战

    本文主要详细介绍了阿里云CC++编译器(GCC、LLVM)工作现状、主流编译器(GCC、LLVM)开源社区参与现状以及多架构(RISC-V)对数据中心的挑战。
    的头像 发表于 06-23 15:26 2949次阅读
    阿里云基础软件<b class='flag-5'>C</b>/<b class='flag-5'>C++</b><b class='flag-5'>编译器</b>的工作现状及挑战

    单片机开发重点-字节对齐问题

    单片机开发重点-字节对齐问题在缺省情况下,C编译器为每一个变量或是数据单元按其自然对界条件分配空间。一般地,可以通过下面的方法来改变
    发表于 11-13 13:06 6次下载
    单片机开发重点-<b class='flag-5'>字节</b><b class='flag-5'>对齐</b>问题

    C编译器缺省字节对齐方式(自然对界)

    缺省情况下,C编译器为每一个变量或是数据单元按其自然对界条件分配空间。
    的头像 发表于 07-29 09:27 2151次阅读

    SuperH C/C++ 编译器包 V.9.04 用户手册

    SuperH C/C++ 编译器包 V.9.04 用户手册
    发表于 01-12 18:45 1次下载
    SuperH <b class='flag-5'>C</b>/<b class='flag-5'>C++</b> <b class='flag-5'>编译器</b>包 V.9.04 用户手册

    SuperH C/C++ 编译器包 V.9.01 用户手册

    SuperH C/C++ 编译器包 V.9.01 用户手册
    发表于 04-21 19:55 0次下载
    SuperH <b class='flag-5'>C</b>/<b class='flag-5'>C++</b> <b class='flag-5'>编译器</b>包 V.9.01 用户手册

    SuperH C/C++ 编译器包 V.9.04 用户手册

    SuperH C/C++ 编译器包 V.9.04 用户手册
    发表于 07-03 18:38 4次下载
    SuperH <b class='flag-5'>C</b>/<b class='flag-5'>C++</b> <b class='flag-5'>编译器</b>包 V.9.04 用户手册

    C7000优化C/C++编译器

    电子发烧友网站提供《C7000优化C/C++编译器.pdf》资料免费下载
    发表于 10-30 09:45 0次下载
    <b class='flag-5'>C</b>7000优化<b class='flag-5'>C</b>/<b class='flag-5'>C++</b><b class='flag-5'>编译器</b>

    TMS320C6000优化C/C++编译器v8.3.x

    电子发烧友网站提供《TMS320C6000优化C/C++编译器v8.3.x.pdf》资料免费下载
    发表于 11-01 09:35 0次下载
    TMS320<b class='flag-5'>C</b>6000优化<b class='flag-5'>C</b>/<b class='flag-5'>C++</b><b class='flag-5'>编译器</b>v8.3.x

    ARM优化C/C++编译器 v20.2.0.LTS

    电子发烧友网站提供《ARM优化C/C++编译器 v20.2.0.LTS.pdf》资料免费下载
    发表于 11-07 10:46 0次下载
    ARM优化<b class='flag-5'>C</b>/<b class='flag-5'>C++</b><b class='flag-5'>编译器</b> v20.2.0.LTS

    MSP430优化C/C++编译器v21.6.0.LTS

    电子发烧友网站提供《MSP430优化C/C++编译器v21.6.0.LTS.pdf》资料免费下载
    发表于 11-08 14:57 0次下载
    MSP430优化<b class='flag-5'>C</b>/<b class='flag-5'>C++</b><b class='flag-5'>编译器</b>v21.6.0.LTS