字节对齐《c和指针》笔记包含位域结构体的内存对齐(32bit,GCC)

摘要:
最近,在使用开发过程中出现了一个小问题。顺便说一下,记录原因和方法--字节对齐C99将int、unsigned int和bool分隔为位字段类型。因为这里没有定义#pragmack,所以默认情况下对齐停止4个字节。结构中的最大数量很长,占4个字节。因此,整个对齐最终停止4个字节。C、 最后,整个结构停止对齐。4) 如果非位字段字段散布在位字段字段之间,则不会停止压缩,并且会根据没有位字段的结构停止对齐。有关详细规则,请参阅我之前的文章:http://blog.csdn.net/todd911/article/details/6528428示例:structtest4{chara:1;charb:1;short;chard:1;};它占用6个字节。

最近使用开发的过程中出现了一个小问题,顺便记录一下原因和方法--字节对齐

    C99划定int、unsigned   int和bool可以作为位域类型。但编译器几乎都对此作了扩展,答应其它类型类型的存在。

    如果结构体中含有位域(bit-field),总结规则如下:(以下代码在x86 32bit系统上测试,gcc 4.1.2)

    1) 如果相邻位域字段的类型相同,且其位宽之和小于类型的sizeof巨细,则前面的字段将紧邻前一个字段存储,直到不能包容为止

    例:

    struct test1 {

    char    a : 2;

    char    b : 3;

    char    c : 3;

    };

    3个变量恰好占1个字节,所以整体只要占1个字节

    2) 如果相邻位域字段的类型相同,但其位宽之和大于类型的sizeof巨细,则前面的字段将从新的存储单元开始,其偏移量为其类型巨细的整数倍

    例:

    struct test2 {

    char    a : 2;

    char    b : 3;

    char    c : 7;

    };

    3个变量超过1个字节,a和b在占一个字节,c占一个字节,所以整体占2个字节。

    3) 如果相邻的位域字段的类型不同,则各编译器的详细实现有差异,VC6采用不压缩方法(不同位域字段存放在不同的位域类型字节中),Dev-C++和GCC都采用压缩方法

    例1:

    struct test3

    {

    char a:1;

    char b:1;

    long c:1;

    char d:2;

    };

    4个变量<=1个字节,所以整体占1个字节,对吧!

    错了,开始我也是这样想的,结果是4个。

    我猜想了一下:

    虽然a,b,c,d加起来只占1个字节,但是最后结构体整体也要停止对齐。

    详细可以查看之前写的不含位域的内存对齐说明http://blog.csdn.net/todd911/article/details/6528428,

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

    每日一道理
这浓浓的母爱使我深深地认识到:即使你是一只矫健的雄鹰,也永远飞不出母爱的长空;即使你是一条扬帆行驶的快船,也永远驶不出母爱的长河!在人生的路上不管我们已走过多远,还要走多远,我们都要经过母亲精心营造的那座桥!

    这边因为没有定义#pragma pack,所以默认按4个字节停止对齐,结构体中最大的数是long,占4个字节,所以最终要按4个字节停止整体对齐。

    我们来验证一下,如果将结构体改成:

    struct test3

    {

    char  a:1;

    char  b:1;

    short c:1;

    char  d:2;

    };

    结果应该是2。

    试一下,确实是2.

    再来修改一下:

    struct test3

    {

    char a:1;

    char b:1;

    long c:31;

    char d:2;

    };

    上面的结构体占12个字节。

    a,b合起来占1个字节,c如果要合到a,b中去,的话就是33bit,超过将按照#pragma pack指定的数值和结构(或结合)最大数据成员长度中,比较小的那个,

    所以c只能自立门户,从第5个字节(偏移量为32bit)开始放置占4个字节,同理最后d也合不进c中去,所以从第9个字节开始放置,最后结构体整体对齐,结果是12.

    总结gcc的压缩方法:

    a.先要取得#pragma pack指定的数值和结构(或结合)最大数据成员长度中,比较小的那个值,这边称为对齐基数。

    b.按照结构体中变量的次序,如果能合在一起且不超过a中的对齐基数的就合并,不能合并的需要自立门户,偏移量为对齐基数的整数倍,继续检查是否能停止合并。。。

    c.最后结构体整体停止对齐。

    4)如果位域字段之间穿插着非位域字段,则不停止压缩,按照不包含位域的结构体停止对齐,详细规则可以参考我以前写的文章:http://blog.csdn.net/todd911/article/details/6528428

    例:

    struct test4

    {

    char a:1;

    char b:1;

    short c;

    char d:1;

    };

    占用6个字节。

文章结束给大家分享下程序员的一些笑话语录: 人在天涯钻,哪儿能不挨砖?日啖板砖三百颗,不辞长做天涯人~

免责声明:文章转载自《字节对齐《c和指针》笔记包含位域结构体的内存对齐(32bit,GCC)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇oracle中取得当前日期,前一天,当前月,前一个月EasyExcel调试记录下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

cjson库的使用以及源码阅读

cjson是一个用c语言开发的json解析库,免费开源只有一个c文件和一个h文件。json和xml功能相似,可以用来传输数据,存储数据以及表达程序当前的状态。 1、下载cjson的源码         https://github.com/DaveGamble/cJSON 2、阅读readme文件可以大概的了解一下cjson的介绍以及使用方法,我尝试着把...

C语言基础:C语言指针(6)

上一节我们讲到了指针和数组, 这次我们来讲解一下指针和字符串, 这次的内容和上一节有相似的地方, 也有全新学习的地方, 让我们一起来看看吧~~下面我们来看一个小例子: #include <stdio.h> int main() { char name[] = "abcde"; name[0] = 'A';...

Centos7中一次性安装开发者工具

这里使用组安装包,一次性安装所有开发者工具。 1、查看有那些组安装包可用。 yum grouplist | more 2、搜索一下有哪些和development有关。 yum grouplist | grep development 查到以下内容: [root@noi ~]# yum grouplist | grep DevelopmentThere is...

Java虚拟机:十八、Java对象大小、对象内存布局及锁状态变化

一个对象占多少字节? 关于对象的大小,对于C/C++来说,都是有sizeof函数可以直接获取的,但是Java似乎没有这样的方法。不过还好,在JDK1.5之后引入了Instrumentation类,这个类提供了计算对象内存占用量的方法。至于具体Instrumentation类怎么用就不说了,可以参看这篇文章如何精确地测量java对象的大小。 不过有一点不同的...

error: ‘for’ loop initial declarations are only allowed in C99 mode

比如写出下面这段程序: for (int i = 0; i < n; ++i) do_something(); 然后用gcc编译,会报‘for’ loop initial declarations are only allowed in C99 mode的错误。 原因是在循环条件中声明变量,只在C99标准中支持,C90标准不支持。 所以改成: int...

【华为云技术分享】鲲鹏弹性云服务器GCC交叉编译环境搭建指南

南七技校林书豪 1、简介 交叉编译,简单地说,就是在一个平台上生成另一个平台上的可执行代码。本指南主要内容为在非ARM架构服务器环境下搭建ARM的GCC编译环境,编译基于ARM架构的应用软件。交叉编译工具链是为了编译、链接、处理和调试跨平台体系结构的程序代码。除了体系结构相关的编译选项以外,其使用方法与Linux主机上的GCC相同。 搭建交叉编译环境,即安...