首页 > 试题广场 >

在#pragma pack(4)和#pragma pack(

[单选题]
下面两个结构体
struct One{
	double d;
	char c;
	int i;
}
struct Two{
	char c;
	double d;
	int i;
}
在#pragma pack(4)和#pragma pack(8)的情况下,结构体的大小分别是
  • 16 24,16 24
  • 16 20,16 20
  • 16 16,16 24
  • 16 16,24 24


编辑于 2016-03-24 15:41:47 回复(13)

许多实际的计算机系统对基本类型数据在内存中存放的位置有限制,它们会要求这些数据的首地址的值是某个数k(通常它为48)的倍数,这就是所谓的内存对齐。


每个特定平台上的编译器都有自己的默认对齐系数32位机一般为464位机一般为8)。我们可以通过预编译命令#pragma pack(k)k=1,2,4,8,16来改变这个系数,其中k就是需要指定的对齐系数;也可以使用#pragma pack()取消自定义字节对齐方式。


struct 或者 union 成员对齐规则如下:


1. 第一个数据成员放在offset0的地方,对齐按照对齐系数和自身占用字节数中,二者比较小的那个进行对齐;

2. 在数据成员完成各自对齐以后,struct或者union本身也要进行对齐,对齐将按照对齐系数和struct或者union中最大数据成员长度中比较小的那个进行;


先局部成员对齐,然后再全局对齐。

发表于 2016-03-24 09:35:56 回复(4)

许多实际的计算机系统对基本类型数据在内存中存放的位置有限制,它们会要求这些数据的首地址的值是某个数k(通常它为48)的倍数,这就是所谓的内存对齐。

每个特定平台上的编译器都有自己的默认对齐系数32位机一般为464位机一般为8)。我们可以通过预编译命令#pragma pack(k)k=1,2,4,8,16来改变这个系数,其中k就是需要指定的对齐系数;也可以使用#pragma pack()取消自定义字节对齐方式。

struct 或者 union 成员对齐规则如下: 

1. 第一个数据成员放在offset0的地方,对齐按照对齐系数和自身占用字节数中,二者比较小的那个进行对齐;

2. 在数据成员完成各自对齐以后,struct或者union本身也要进行对齐,对齐将按照对齐系数和struct或者union中最大数据成员长度中比较小的那个进行;

先局部成员对齐,然后再全局对齐。


#pragma pack(4)时:
One的大小:
口口口口 d
口口口口 d
口口口   c (补3位对齐)
口口口口 i
共:4+4+4+4 = 16;
Two的大小:
口口口 c (补3位对齐)
口口口口 d
口口口 d
口口口口 i
共:4+4+4+4 = 16;
================================
#pragma pack(8)时:
One的大小:
口口口口 口口口口 d
口口口 口口口 c占1位,i紧挨着占4位,再补3位对齐
共:8+8 = 16;
Two的大小:
口口口口口口口    c(补7位对齐)
口口口口 口口口口 d
口口口口口口口 i (补4位对齐)
共:8+8+8 = 24;
发表于 2020-07-07 10:27:39 回复(0)
每个特定平台上的编译器都有自己的默认“对齐系数”(也叫对齐模数)。程序员可以通过预编译命令#pragma pack(n),n=1,2,4,8,16来改变这一系数,其中的n就是你要指定的“对齐系数”。
规则:
1、数据成员对齐规则:结构(struct)(或联合(union))的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员的对齐按照#pragma pack指定的数值和这个数据成员自身长度中,比较小的那个进行
2、结构(或联合)的整体对齐规则:在数据成员完成各自对齐之后,结构(或联合)本身也要进行对齐,对齐将按照#pragma pack指定的数值和结构(或联合)最大数据成员长度中,比较小的那个进行
-----百度百科(内存对齐)
发表于 2017-03-24 21:15:44 回复(0)
#pragma pack(4)情况下
one:4*2+(1+3)+4=16
two :(1+3+)4*2+4=16

pack 8情况下
one:8+(1+3+4)=16
two: (1+7)+8+(4+4)=24
发表于 2016-08-02 09:20:44 回复(2)
按结构体里面最大的元素大小对齐,如果最大的元素大小比#progmma pack(n)中的n小,就按n来对齐。假设结构体里面的元素最大的大小是e,定义了 #progmma pack(n)(默认32位是4,64位是8),那么对齐的大小: max(e,n)。
发表于 2016-03-23 21:20:36 回复(2)
那TWO 中第一个为什么不是8+8+8呢?不是按8对齐么?怎么上面是按4对齐的?
发表于 2016-11-30 14:04:01 回复(0)
        #pragma pack(4)代表变量以四字节对齐方式, #pragma pack(8)表示变量以8字节方式对齐。
       程序编译器对结构的存储的特殊处理确实提高CPU存储变量的速度,但是有时候也带来了一些麻烦,我们也屏蔽掉变量默认的对齐方式,自己可以设定变量的对齐方式。
       编译器中提供了 #pragma  pack(n)来设定变量以n 字节对齐 方式。n字节对齐就是说变量存放的起始地址的 偏移量 有两种情况:第一、如果n大于等于该变量所占用的字节数,那么偏移量必须满足默认的对齐方式,第二、如果n小于该变量的类型所占用的字节数,那么偏移量为n的倍数,不用满足默认的对齐方式。结构的总大小也有个约束条件,分下面两种情况:如果n大于所有 成员变量 类型所占用的字节数,那么结构的总大小必须为占用空间最大的变量占用的空间数的倍数;否则必须为n的倍数。
structOne{
    doubled;
    charc;
    inti;
}
structTwo{
    charc;
    doubled;
    inti;
}
      例如在 #pragma pack(4)模式下:
      结构体One对齐方式为:
     ^^^^^^^^  double  d;    占八个字节
     ^****         charc;        占1个字节,*代表补齐三个字节
     ^^^^         int  i;           占4个字节
所以共总是8+4+4=16个字节。
以下情况类似,注意八字节对齐。      
编辑于 2017-05-26 22:36:17 回复(0)
预编译命令:#pragma pack(n) ,用来改变对齐系数,其中n即为要指定的对齐系数。
structOne{
    doubled;
    charc;
    inti;
}
structTwo{
    charc;
    doubled;
    inti;
}
(实际占位用下划线表示,补位没有下划线)
#pragma pack(4)时:
One的大小:
口口口口 d
口口口口 d
口口口   c (补3位对齐)
口口口口 i
共:4+4+4+4 = 16;
Two的大小:
口口口 c (补3位对齐)
口口口口 d
口口口 d
口口口口 i
共:4+4+4+4 = 16;
================================
#pragma pack(8)时:
One的大小:
口口口口 口口口口 d
口口口 口口口 c占1位,i紧挨着占4位,再补3位对齐
共:8+8 = 16;
Two的大小:
口口口口口口口    c(补7位对齐)
口口口口 口口口口 d
口口口口口口口 i (补4位对齐)
共:8+8+8 = 24;
选C

编辑于 2016-08-02 16:18:07 回复(4)
感觉没什么用的
发表于 2017-03-04 20:34:57 回复(0)
对齐数是:编译器默认的一个数与这个成员变量的较小值。
发表于 2022-04-20 21:58:46 回复(0)
内存对齐
发表于 2021-11-26 08:39:15 回复(0)

pragmatic pack 对齐系数

发表于 2020-03-05 17:48:12 回复(0)
内存对齐存在于两个地方:
1.结构内部元素之间需要考虑对齐
2.整个结构最后也要考虑对齐
发表于 2019-07-22 23:15:14 回复(0)
Mark
发表于 2018-03-28 14:16:52 回复(0)
结构体内自身成员的自对齐和结构体总大小的有效对其,这两个都要满足吧?我为什么不是16,20,16,24呢?其中20是1+7+8+4。其中+7是因为double 自对齐,它只能以0.8.16.24这样的自身长度的整数倍开始,不是这样的吗?求大神指教!谢谢
发表于 2017-07-04 11:05:57 回复(0)
如果#pramga pack(n)中的n大于结构体成员中任何一个成员所占用的字节数,则该n值无效。编译器会选取结构体中最大数据成员的字节数为基准进行对其
发表于 2016-07-29 14:48:56 回复(0)
#pragma pack(4)下double类型不是按8字节对齐的吗??占8字节大小?
发表于 2016-03-28 20:37:55 回复(2)