# C语言结构体中的数据对齐

C++实验课的时候，坐在我旁边的同学问了我一个问题：

struct

{

char a;

int b;

double c;

} sa;

struct

{

int a;

char b;

} sa;

struct

{

int a;

char b;

double c;

} sb;

struct

{

int a;

double c;

char b;

} sc;

struct

{

int a;

char b, c, d, e,;

} sa1;

struct

{

int a;

char b;

int c;

} sa2;

sb中的int a 4个字节，紧接着的char b占用1个字节，但是char b随后的double c需要占用8个字节，所以char bdouble c不能挤在一个4个字节的单位里面。于是在char bdouble c之间填了3个字节的空位，实现与其后的数据的对齐，这样就不难理解为什么sizeof(sa1)=8了。

sbsc的唯一区别就是char bdouble c的定义次序颠倒了，结果使得sizeof(sb)sizeof(sc)产生了差别。能想到的唯一解释是sbsc的对齐的最小单位不一样了。于是我又设计了一组对比：

struct

{

int a;

int d;

double c;

char b;

} sc1;

struct

{

int a;

double c;

} sc2;

sc1sc的基础上在int a后面紧接着加上了int d;但是结果sizeof(sc1)=24= sizeof(sc)，这说明在int a的后面存在4个字节的空位。看来这次系统给结构体内的变量分配空间的时候，不再像sa那样以4个字节为一组了。

1、在程序内部用#pragma pack(n)指定<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

#pragma pack(1)可以使编译器不在struct内留空位。

2、  用编译指令

CL /Zp8

#include

using namespace std;

struct    // packing is 8

{

int a;

char b;

} sa;

#pragma pack(push,1) // packing is now 1

struct

{

int a;

char b;

double c;

} sb;

#pragma pack(pop) // packing is 8

struct

{

int a;

double c;

char b;

} sc;

int main(void)

{

cout << "sizeof(sa) =" << sizeof(sa) << endl;

cout << "sizeof(sb) =" << sizeof(sb) << endl;

cout << "sizeof(sc) =" << sizeof(sc) << endl;

return 0;

}

struct    // packing is 8

{

int a;

char b;

} sa;

struct    // packing is 8

{

int a;

int c;

char b;

} sa;

packing值小于结构体内占用空间最多成员占用的字节数的时候，以packing值为准。

#pragma pack(push,1) // packing is now 1

struct

{

int a;

char b;

double c;

} sb;

Specifies packing alignment for structure, union, and class members. Whereas the packing alignment of structures, unions, and classes is set for an entire translation unit by the /Zp option, the packing alignment is set at the data-declaration level by the pack pragma. The pragma takes effect at the first structure, union, or class declaration after the pragma is seen; the pragma has no effect on definitions.

When you use #pragma pack(n), where n is 1, 2, 4, 8, or 16, each structure member after the first is stored on the smaller member type or n-byte boundaries. If you use #pragma pack without an argument, structure members are packed to the value specified by /Zp. The default /Zp packing size is /Zp8.

The show option causes the C4810 warning to issue, displaying the current pack value.

The compiler also supports the following enhanced syntax:

#pragma pack( [ [ { push | pop}, ] [ identifier, ] ] [ n ] )

This syntax allows you to combine program components into a single translation unit if the different components use pack pragmas to specify different packing alignments.

Each occurrence of a pack pragma with a push argument stores the current packing alignment on an internal compiler stack. The pragma’s argument list is read from left to right. If you use push, the current packing value is stored. If you provide a value for n, that value becomes the new packing value. If you specify an identifier, a name of your choosing, the identifier is associated with the new packing value.

Each occurrence of a pack pragma with a pop argument retrieves the value at the top of an internal compiler stack and makes that value the new packing alignment. If you use pop and the internal compiler stack is empty, the alignment value is that set from the command-line and a warning is issued. If you use pop and specify a value for n, that value becomes the new packing value. If you use pop and specify an identifier, all values stored on the stack are removed from the stack until a matching identifier is found. The packing value associated with the identifier is also removed from the stack and the packing value that existed just before the identifier was pushed becomes the new packing value. If no matching identifier is found, the packing value set from the command line is used and a level-one warning is issued. The default packing alignment is 8.

The new, enhanced functionality of the pack pragma allows you to write header files that ensure that packing values are the same before and after the header file is encountered:

In the previous example, the current pack value is associated with the identifier enter_include1 and pushed, remembered, on entry to the header file. The pack pragma at the end of the header file removes all intervening pack values that may have occurred in the header file and removes the pack value associated with enter_include1. The header file thus ensures that the pack value is the same before and after the header file.

The new functionality also allows you to use code, such as header files, that uses pack pragmas to set packing alignments that differ from the packing value set in your code:

In the previous example, your code is protected from any changes to the packing value that might occur in include.h.

• 本文已收录于以下专栏：

## C语言对其方式--struct数据结构必学

• jk110333
• 2014年02月15日 13:21
• 4630

## C语言字节对齐、结构体对齐最详细的解释

• lanzhihui_10086
• 2015年03月17日 21:57
• 9326

## 结构体struct 联合体union 及内存对齐

• Aiphis
• 2015年09月24日 10:33
• 2466

## C语言中的结构体数据存储-对齐规则

(1)什么是字节对齐 　　一个变量占用 n 个字节，则该变量的起始地址必须能够被 n 整除，即: 每个变量的起始存放地址 % n = 0，      对于结构体，这个 n 取其成员种的数据类型...
• yangxiaochun318
• 2014年02月03日 22:03
• 630

## java 与C语言使用socket通信传递结构体数据

• 2013年09月27日 23:55
• 3KB
• 下载

## java 与C语言传递结构体数据

• 2017年05月23日 14:29
• 46B
• 下载

## C语言数据类型大小和结构体中变量…

【注释】本博文介绍十分详细，本人收益良多，特此收藏。 【出处】源自网络，原始出处未知。   C语言数据类型大小和结构体中变量的地址分配方法 数据类型:   char  short   i...
• shangyaowei
• 2013年12月19日 20:41
• 279

## C语言入门（15）——结构体与数据抽象

• yincheng01
• 2014年06月30日 12:25
• 1387

## php读取二进制流（C语言结构体struct数据文件）

• climb_up
• 2014年04月09日 09:40
• 597

## 黑马程序员----C语言复杂数据类型之结构体与枚举篇

-------android培训、java培训、IOS培训、期待与您交流！------- 在iOS开发中，结构体是经常用到的数据类型，使用频率不亚于指针...
• xiaoqinqinqin0
• 2015年04月19日 11:20
• 234

举报原因： 您举报文章：C语言结构体中的数据对齐 色情 政治 抄袭 广告 招聘 骂人 其他 (最多只允许输入30个字)