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

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

3天内不再提示

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

电子工程师 来源:嵌入式与Linux那些事 作者:嵌入式与Linux那些 2022-07-29 09:27 次阅读

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


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

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

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

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

例子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结构体中,最大的成员为flaot x3,因些此结构体的自然对界条件为4字节对齐。则结构体长度就为12字节,内存布局为1100 1111 1000。

例子2:


							
#include <stdio.h>//#pragma pack(2)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 = 8int main(void) { printf("length1 = %d. ",length1); printf("length2 = %d. ",length2); printf("length3 = %d. ",length3); printf("length4 = %d. ",length4); return 0; }

改变缺省的对界条件(指定对界) · 使用伪指令#pragma pack (n),C编译器将按照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。

例子:


							
#include <stdio.h>#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 = 8int main(void) { printf("length1 = %d. ",length1); printf("length2 = %d. ",length2); printf("length3 = %d. ",length3); printf("length4 = %d. ",length4); return 0; }

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

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

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

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

审核编辑:汤梓红


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

    关注

    1

    文章

    39

    浏览量

    13944
  • 字节对齐
    +关注

    关注

    0

    文章

    5

    浏览量

    1508

原文标题:又错了,字节对齐及#pragma pack的使用

文章出处:【微信号:嵌入式与Linux那些事,微信公众号:嵌入式与Linux那些事】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    几款C语言编译器推荐

    一些刚开始接触C语言编译的网友想下载一款C语言编译器来使用,不过,网络上有不少C语言编译器相关的
    发表于 09-05 09:19 1w次阅读

    c语言中的字节对齐

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

    C语言-结构体对齐详解

    :32位编译器,一般编译器默认对齐方式是4字节对齐。#include<stdio.h>
    发表于 07-12 16:41

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

    单片机开发重点-字节对齐问题在缺省情况下,C编译器为每一个变量或是数据单元按其自然
    发表于 11-22 06:06

    IccAVR C 编译器的使用

    IccAVR C 编译器的使用自 ATMEL 的AT90 系列单片机诞生以来有很多第三方厂商为AT90 系列开发了用于程序开发的C 语言工具ATMEL 公司推荐的第三方C
    发表于 04-09 14:48 172次下载

    C语言编译器

    电子发烧友网站提供《C语言编译器.exe》资料免费下载
    发表于 01-15 17:45 50次下载

    IAR_AVR_C编译器的使用

    IAR_AVR_C编译器的使用A
    发表于 06-15 17:15 29次下载

    MPLAB® XC8 C编译器的架构特性

    本视频介绍了MPLAB® XC8 C编译器的架构特性。该编译器编译过程不同于传统的编译器,采用了一种称为"OCG(全知代码生成)"的技术。
    的头像 发表于 05-23 12:47 5938次阅读
    MPLAB® XC8 <b class='flag-5'>C</b><b class='flag-5'>编译器</b>的架构特性

    如何选择PIC单片机的C编译器

    PIC单片机的C编译器只有HI-TECH公司出品PICC编译器,和CCS公司的CCS编译器。还有PIC的生产商Microchip公司自行生产的只针对PIC18/PIC24/dsPIC/
    发表于 03-29 14:09 5350次阅读

    既然C编译器C语言写,那么第一个C编译器是怎样来的?

    既然C编译器C语言写的,那第一个C编译器是怎样来的?
    的头像 发表于 02-25 15:47 3118次阅读

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

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

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

    单片机开发重点-字节对齐问题在缺省情况下,C编译器为每一个变量或是数据单元按其自然
    发表于 11-13 13:06 6次下载
    单片机开发重点-<b class='flag-5'>字节</b><b class='flag-5'>对齐</b>问题

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

    C/C++编译器缺省字节对齐方式
    的头像 发表于 04-15 11:24 954次阅读

    R32C/100系列C编译器包V.1.01 C编译器用户手册

    R32C/100系列C编译器包V.1.01 C编译器用户手册
    发表于 04-28 19:54 1次下载
    R32<b class='flag-5'>C</b>/100系列<b class='flag-5'>C</b><b class='flag-5'>编译器</b>包V.1.01 <b class='flag-5'>C</b><b class='flag-5'>编译器</b>用户手册

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

    的默认对齐方式和规则 结构体在Keil Arm工程中的默认对齐方式是根据编译器或者编译器选项来定
    的头像 发表于 01-05 14:40 3463次阅读