[音樂]
下面我们通过一些例子,来讲解这个C语言当中对齐方式的设定。
在C语言程序当中呢,我们可以通过一些编译指导语句,来设定对齐方式,
这个编译指导语句,告诉编译器 对指定的结构体或者类,
它内部的成员变量,采用什么样的对齐方式。
如果这个自然边界, 比如说int型的自然边界就是4,
short型的自然边界就是2,float型的自然边界就是4,等等,
这些自然边界比n大的时候,按照n字节对齐, 那比它小的话,那就按照自然边界对齐,
那么如果是缺省,就是没有这个,或者呢这个地方没有参数,没有给出值,
我们这时候也表示是按自然边界对齐。
在有些这个变量,比如说结构体啊,类啊,联合体啊等等,这些变量
后面我们可以通过这个的一个语句来设定对齐方式, 这个意思是说,这些变量
比如说某一个结构体,或者一个联合体或者一个单独的变量, 它必须按m字节对齐。
当然这个m必须是2的多少次方,也就是 m必须是0,2,4,8,16等等,然后呢
这个变量占用的空间大小也应该是m的整数倍,
这样就可以保证连续申请空间的时候,这个结构体或者联合体或者类,或者是单独的变量
作为一个数组元素的时候,每一个元素也按m字节对齐,
因为它的大小是m的倍数。
紧接着一个一个的元素当然都是按m对齐的,这个是这个意思。
那如果是 给出来的是这样的一个语句的话,那表示不对齐,
也就是我们前面讲的紧凑方式,随后按顺序直接存放 直接分配,下面是一个例子,
在这个例子当中,指出来的这个n呢是等于4, 等于4的意思就是说,里面的成员
它的自然边界如果比4大的话,就按4字节边界对齐,
否则就按自然边界对齐,是这个意思。
这个结构当中,有这么一个语句, 这边的m是1024,
说明这个变量的起始地址应该是
1024的整数倍,也就是按1024字节对齐,并且
这个变量,也就是这个structure变量 所有的分量加起来所占的
空间应该是1024字节, 因此我们打印出来的时候,这个structure
size 应该是这个ts的size,应该是等于1024,
并且它是按1024对齐的,所以我们第一句打出来的这个size是1024。
然后,第二个要打印的是f1。
相对于这个ts起始地址的位移量,那么很显然f1
它的位移量当然就是0,然后f2的位移量是多少呢?
因为f1占了4个字节,这个表示32位的一个数据unsized
占了四个字节,所以 这个f2的位移量当然就应该是4,
起始地址是4,因为它占了4个字节,占据了 0,1,2,3这四个位置,所以它就应该是4。
然后呢,它的这个应该是,因为它占了
1个字节,所以直接就是占用了位移量为4的那个地方的单元。
然后,紧接着所以它就是5, 因为这些的自然边界都比4小,所以按自然边界对齐。
紧接着是f4,而f4是一个32位的无符号素,
所以占4个字节,所以它的自然边界呢是4,
而4字节边界对齐,4和4是相等的,
所以这时候,它的这个边界就应该是4的倍数。
5接着是6,6不是4的倍数,7也不是,所以
紧接着它就是8,然后它占4个字节 8,9占4个字节,8,9,10,11。
然后这边呢,就应该紧接着f5,这占了8,9,10,11这四个位置,
所以它应该是12这个位置,那么12这个对齐 满足不满足条件呢?我们来看一下。
f5是8字节边界对齐的自然边界,
也就是说它的类型是8个字节的无符号素,因此它的自然边界是8,
而8比4大,所以按4边界对齐。
而12是4的倍数,所以这个 12就是f5的位移量,相对于这个结构
开始走地址,它的位移量就是12,12的 十六进制就是c,这就是8,5,4。
下面这个例子 是在Linux平台上面的。
Linux平台,我们前面讲过,它的这个对齐方式比较宽松, 除了short型是按2字节边界对齐,
char型不对齐,其他的全是按4字节边界对齐的,这是Linux的对齐方式。
所以这个地方是被注解掉的, 所以这个应该是按自然边界对齐,
但是呢,这边有这么一个限定语句 就使得这里面的每一个分量
按紧凑方式进行分配,所以它是1个字节,
它是4个字节,挨着放,这个short型是2字节, long
long是8个字节,因为它是64位的,所以整个加起来
占用了这个空间,占用了15个字节。
然后我们来看下面一个,下面这个
结构,它没有约束条件,所以它是按自然边界对齐。
这个自然边界对齐是占1个字节,然后这呢,是int型的,所以是按4边界对齐,
所以这边要空3个, 这个就从第4个
位移量开始,并且占4个字节,这样的话就是 这是占了4个字节,
占1个字节,空3个字节,所以4个字节 这,4个字节,4个字节完了以后,紧接着这个应该是
2的倍数的边界上面,因为4,5,6,7然后它就是占的是第8,第9个单元,所以是
2个字节,但是 紧接着的这个
对齐方式,我们讲了Linux里面 除了short以外都是按4边界对齐的,所以这边
是8,9两个单元 占用了,紧接着10不是4的倍数
所以10这个地方,这边是8,9占了这个2个,
紧接着的这个10,11, 这两个是浪费了2个空间,所以
这个x3占了2个空间,然后再浪费了2个空间,它占了4个字节
然后这个x4占几个字节呢?
是long long型的,当然是8个字节,所以我们可以看到test1
它整个的这个所占的空间应该是4 加4加4加8
3,4,12加8,所以它占了20个字节的空间, 它的size是20个字数。
然后test2,这里面多了一个这个限定, 这个限定是说,它的起始地址必须
是8的倍数,并且这个长度也要是8的倍数, 而这个长度,我们按自然边界对齐的话,它是20,
然后我们算出来是20,20不是8的倍数, 所以还要加4个字节,所以它应该是24个字节
除以8等于3,也就是24是8的倍数。
因此我们可以看到它最后打印出来的这个结果,
应该是15,20,24, 刚才我们才讲过。
最后我们再来看一个例子,这边 注解去掉了,其他都还是一样的,
这种情况下,这个表示 如果自然边界比这个大的话,
就按它来对齐,而这个里面我们知道 1当然是最小的,也就是说
这个编译指导语句表示后面所有的这些都不按边界对齐
就是都是按1字节边界对齐,因为1比所有的都小,
所以第一个,很显然是15 第二个也是15,这是不对齐的,这是按
1边界对齐,所以也是不对齐的,是15,这个因为按
1字节边界对齐,也就是不对齐是15,然后15不是8的倍数,现在我们要
限定它是8的倍数,所以就是16,这个应该很好理解。
在这个编译指导语句下面,这些都是不对齐的,
那就都是紧凑方式,在这个条件限定下,它的
这个大小,要是8的倍数,15呢要加1变成16, 因为打印出来的是这个sizeof。
如果我们把这个改成2,刚才是1
现在这个地方是2,同样的这个情况应该是什么样子的呢?还是Linux平台,
很显然第一个因为是,虽然这个是2 了,但这个地方表示紧凑方式,相当于是1,
所以这个还是15,然后 我们来看它,这个还是占1个字节,然后呢
空1个字节,因为这个 对齐是4,4比2要大
所以按2边界对齐方式,所以它的这个 起始地址只要是2的倍数,因为01,所以呢还是2,所以这
是2个字节,然后这边是4的字节。
紧接着这边一定是2的边界对齐的,有2个字节,
所以我们可以看到这边正好是8,所以这个地方应该 是2的倍数,因为它的自然边界是4,
而4比2大,所以只要按2边界对齐就行了,所以这个地方因为肯定都是偶数,
因此它的起始地址一定是2的倍数,因此这是8, 这边所以加起来应该是2加4加2
加8是16字节,最后一个
是自然的边界,就是16字节,按这个以pack 2的前提条件下
它是16字节,而16字节又正好是8的倍数,所以它也是16字节,
最后打印出来的结果应该是 15,16,16,这边是16,这边也是16。
[音樂] [音樂]