`

param pack

阅读更多
在C语言中,结构是一种复合数据类型,其构成元素既可以是基本数据类型(如int、long、float等)的变量,也可以是一些复合数据类型(如数组、结构、联合等)的数据单元。在结构中,编译器为结构的每个成员按其自然对界(alignment)条件分配空间。各个成员按照它们被声明的顺序在内存中顺序存储,第一个成员的地址和整个结构的地址相同。

例如,下面的结构各成员空间分配情况:
struct test
{
     char x1;
     short x2;
     float x3;
     char x4;
};

结构的第一个成员x1,其偏移地址为0,占据了第1个字节。第二个成员x2为short类型,其起始地址必须2字节对界,因此,编译器在x2和x1之间填充了一个空字节。结构的第三个成员x3和第四个成员x4恰好落在其自然对界地址上,在它们前面不需要额外的填充字节。在test结构中,成员x3要求4字节对界,是该结构所有成员中要求的最大对界单元,因而test结构的自然对界条件为4字节,编译器在成员x4后面填充了3个空字节。整个结构所占据空间为12字节。

更改C编译器的缺省字节对齐方式
在缺省情况下,C编译器为每一个变量或是数据单元按其自然对界条件分配空间。一般地,可以通过下面的方法来改变缺省的对界条件:
     · 使用伪指令#pragma pack (n),C编译器将按照n个字节对齐。
     · 使用伪指令#pragma pack (),取消自定义字节对齐方式。

另外,还有如下的一种方式:
     · __attribute((aligned (n))),让所作用的结构成员对齐在n字节自然边界上。如果结构中有成员的长度大于n,则按照最大成员的长度来对齐。
     · __attribute__ ((packed)),取消结构在编译过程中的优化对齐,按照实际占用字节数进行对齐。

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

( via http://blog.csdn.net/wenddy112/articles/300583.aspx )

下面有一道在 CSDN论坛 上讨论火热的题:

Intel和微软和本公司同时出现的面试题

#pragma pack(8)

struct s1{
short a;
long b;
};

struct s2{
char c;
s1 d;
long long e;
};

#pragma pack()


1.sizeof(s2) = ?
2.s2的c后面空了几个字节接着是d?

感谢 redleaves(ID最吊的网友) 的解答,结果如下:

sizeof(S2)结果为24.
成员对齐有一个重要的条件,即每个成员分别对齐.即每个成员按自己的方式对齐.
也就是说上面虽然指定了按8字节对齐,但并不是所有的成员都是以8字节对齐.其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里是8字节)中较小的一个对齐.并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节.
S1中,成员a是1字节默认按1字节对齐,指定对齐参数为8,这两个值中取1,a按1字节对齐;成员b是4个字节,默认是按4字节对齐,这时就按4字节对齐,所以sizeof(S1)应该为8;
S2 中,c和S1中的a一样,按1字节对齐,而d 是个结构,它是8个字节,它按什么对齐呢?对于结构来说,它的默认对齐方式就是它的所有成员使用的对齐参数中最大的一个,S1的就是4.所以,成员d就是按4字节对齐.成员e是8个字节,它是默认按8字节对齐,和指定的一样,所以它对到8字节的边界上,这时,已经使用了12个字节了,所以又添加了4个字节的空,从第16个字节开始放置成员e.这时,长度为24,已经可以被8(成员e按8字节对齐)整除.这样,一共使用了24个字节.
                          a    b
S1的内存布局:11**,1111,
                          c    S1.a S1.b     d
S2的内存布局:1***,11**,1111,****11111111

这里有三点很重要:
1.每个成员分别按自己的方式对齐,并能最小化长度
2.复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度
3.对齐后的长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐

补充一下,对于数组,比如:
char a[3];这种,它的对齐方式和分别写3个char是一样的.也就是说它还是按1个字节对齐.
如果写: typedef char Array3[3];
Array3这种类型的对齐方式还是按1个字节对齐,而不是按它的长度.
不论类型是什么,对齐的边界一定是1,2,4,8,16,32,64....中的一个.

测试的编译器:

GCC 2.95 3.1 3.3 3.4 4.0
MS C/C++ 7.0 7.1 8.0 beta
Borland C/C++ 5.6 6.0
Intel C/C++ 7.0 8.0 8.1
DigitalMars C/C++ 8.4
OpenWatcom 1.3
Codeplay C/C++ 2.1.7
分享到:
评论

相关推荐

    sqlcore数据库防注入分析系统

    sqlcore-驱动版本---选择你刚才的版本, Pack 版本,系统进行处理版本处理,处理完成后弹出打包完成的提示对话框 9.下载驱动 视图分析---》版本视图---》下载该版本 下载你刚才处理的版本 10. 配置sqlcore到你的...

    .NET获取Html字符串中指定标签的指定属性的值

    /// <param name="attr">指定属性名</param> /// 包含所有匹配属性值的列表 private List<string> GetHtmlAttr(string html, string tag, string attr) { // 正则表达式,用于匹配指定的标签 Regex re = new Regex...

    webXML样板1

    在webXML样板1中,定义了一个名为`HelloServlet`的Servlet,类名为`web.pack1.HelloServlet`,并配置了两个初始化参数:`user`和`password`。 servlet-mapping元素 `<servlet-mapping>`元素用于将Servlet映射到特定...

    基于python的任意波形发生器软件及源码解析.docx

    wav_file.writeframes(struct.pack('h', int(s * amplitude))) ``` #### 3. 关键代码解析 - **正弦波信号函数** (`createSine`):通过`numpy.sin()`函数生成正弦波。这里的频率(`frequency`)表示每秒波动的次数...

    android如何默认打开小区广播具体实现

    在nvram_cust_pack.c中COMMON_NVRAM_EF_SMSAL_COMMON_PARAM_DEFAULT 代码如下: kal_uint8 const COMMON_NVRAM_EF_SMSAL_COMMON_PARAM_DEFAULT[] = { #if defined (__CS_SERVICE__) && defined (__SMS_OVER_PS_...

    webservice的简介和具体的代码实现

    3. **安装Tomcat5.0 for Java WSDP 1.4**:这是一个专门为Java WebServices Developer Pack (JWSDP)制作的Web Container版本。 4. **安装JWSDP 1.4**:这是Java构建WebService的相关工具集合。 **安装Tomcat5.0 for...

    贝叶斯主观推理算法java源码

    * @param args String[] */ public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { public void run() { try { UIManager.setLookAndFeel(UIManager. ...

    tcl/ck大全

    - **命令加参数形式**:Tcl 语句通常以命令开头,后跟一系列参数,例如 `command [param1] [param2] ...`。 #### 3. Tcl/Tk 总体结构与应用场景 - **总体结构**:Tcl/Tk 可以被看作是一个完整的编程环境,包括了...

    statebasedml:使用基于状态的机器学习训练数据集的Python库

    pack :将字符串打包成较短的字符串而不会丢失信息 位折叠 导入基于状态的ml.bitfold from statebasedml import bitfold 位折叠有2种方法 gen_param() :生成折叠的参数 fold() :实际上折叠输入数据 gen_param ...

    赛尔号发包例子以及逆向过程-易语言

     loc3_ = this.pack(this.userID,param1,param2);  loc3_.position = 0;  loc4_ = MessageEncrypt.encrypt(loc3_);//这里就开始加密了  writeBytes(loc4_);//整个数据丢给  flush();//这里就是发送数据出去...

    JFreeChart使用总结

    frame.pack(); frame.setVisible(true); ``` ## 应用于 Web 开发 ### 7.1 在 Eclipse 中创建 Tomcat 工程 首先创建一个 Dynamic Web Project,然后在项目中配置 Tomcat 服务器。 ### 7.2 创建 web.xml 在 `WEB-INF...

    java 小程序

    package pack02; public class CycUtmost { /** * @param args */ public static void main(String[] args) { int end = Integer.MAX_VALUE ; int start = end - 50 ; int count = 0 ; for(int i=...

    解析php做推送服务端实现ios消息推送

    pack('H*', str_replace(' ', '', $deviceToken)) . pack("n",strlen($payload)) . $payload; // 发送消息 fwrite($fp, $msg); ``` 在实际开发中,你可能会遇到各种挑战,如网络问题、证书过期、payload格式错误...

    mavlink_interface:使用Mavlink协议的Ardupilot的简单C ++接口

    通过`mavlink_msg_param_value_pack()`创建参数消息,然后发送给Ardupilot,即可完成参数的设置。 在实现过程中,需要注意的是,Mavlink协议有多种版本,包括Mavlink 1和Mavlink 2。不同版本在数据类型、消息大小和...

    DATASTAGE经验积累与分享

    dsjob –run [ –mode [ NORMAL | RESET | VALIDATE ] ] [ –param name=value ] [ –warn n ] [ –rows n ] [ –wait ] [ –stop ] [ –jobstatus] [–userstatus] [-local] project job 通过使用jobstatus命令,...

    ASP与数据库,有用的代码(转贴,摘贴)

    - IIS (Internet Information Server) Service Pack 3 及其以上版本 3. **NT workstation 4.0工作站平台**: - PWS (Personal Web Server) NT workstation版 - 最新版的IE浏览器 #### 三、网页制作软件推荐 - ...

    ASP.NET汉字转拼音 - 输入汉字获取其拼音的具体实现

    微软为了让开发者能够更好地处理国际化语言的互转,专门提供了Microsoft Visual Studio International Pack扩展包,以便于实现各国语言的转换,其中包括了汉字转拼音的功能。 具体实现过程中,开发人员首先需要去...

    ASP与数据库运用:密码验证

    - **Windows NT 4.0/5.0服务器平台**:应选择IIS (Internet Information Server) Service Pack 3及以上版本。 - **NT workstation 4.0工作站平台**:可使用PWS NT workstation版,同时需配备最新版的IE浏览器。 ###...

    SMS小区广播相关

    在这个文件中,有一个数组 COMMON_NVRAM_EF_SMSAL_COMMON_PARAM_DEFAULT,其中第 8 个 byte 就是小区广播的开关,1 表示打开,0 表示关闭。 如果想要默认打开小区广播,只需要将数组中的对应值设置为 0x01。如果想...

Global site tag (gtag.js) - Google Analytics