有关字节对齐

#pragma pack(x) 编译时x字节对齐
#pragma pack() 取消字节对齐
__attribute__((packed)) 编译时数据紧凑的拼接在一起
__attribute__((aligned(x))) 分配地址空间时是x字节对齐
struct foo {
    char a;
    int x[2] __attribute__ ((packed));
};

#pragma pack(n)attribute((aligned(m)))区别:
前者告诉编译器结构体或类内部的成员变量相对于第一个变量的地址的偏移量的对齐方式,缺省情况下,编译器按照自然边界对齐,当变量所需的自然对齐边界比n大 时,按照n对齐,否则按照自然边界对齐;后者告诉编译器一个结构体或者类或者联合或者一个类型的变量(对象)分配地址空间时的地址对齐方式。即如果将__attribute__((aligned(m)))作用于一个类型,那么该类型的变量在分配地址空间时,其存放的地址一定按照m字节对齐(m必 须是2的幂次方)。并且其占用的空间,即大小,也是m的整数倍,以保证在申请连续存储空间的时候,每一个元素的地址也是按照m字节对齐。 attribute((aligned(m)))也可以作用于一个单独的变量,在windows平台上是__declspec__(align(m))。
在ios platform上如果使用位结构,则一直是packed格式,加以上指令完全不起作用。but如果不使用位结构则和各个指令都是可用的。
内存对齐机制是为了减少内存访问次数=>减少io,提升执行速度

__attribute__((aligned(x)))只有在分配地址空间时才起作用,如果所标识的是栈数据则不起作用,如下就应该改为global,static or heap
#include <stdio.h>
int main(void)
{
	float a[4] __attribute__((aligned(0x1000))) = {1.0, 2.0, 3.0, 4.0};
	printf("%p %p %p %p\n", &a[0], &a[1], &a[2], &a[3]);
}

字节对齐有两条原则(n <= #pragma pack(n)):

1,struct成员起始地址对齐
对齐的size=min(n, sizeof(self))
数据成员对齐规则:结构(struct)(或联合(union))的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员的对齐按照#pragma pack指定的数值和这个数据成员自身长度中,比较小的那个进行。
2,struct size对齐
对齐的size=min(n, max(sizeof(a, b, c ...)))
结构(或联合)的整体对齐规则:在数据成员完成各自对齐之后,结构(或联合)本身也要进行对齐,对齐将按照#pragma pack指定的数值和结构(或联合)最大数据成员长度中,比较小的那个进行。

#pragma pack(16)
struct ooo {
    char a;
    int b;
    double c;
    short d;
    char e;
}; // __attribute__((packed));
#pragma pack()
ooo __;

printf("oo size: %lu addr: %p, %p, %p, %p, %p\n",
  sizeof(__), &__.a, &__.b, &__.c, &__.d, &__.e);
gcc => oo size: 24 addr: 0x2521a34, 0x2521a38, 0x2521a3c, 0x2521a44, 0x2521a46
ios => oo size: 20 addr: 0x2521a34, 0x2521a38, 0x2521a3c, 0x2521a44, 0x2521a46
注释:在ios平台上应该是pack最大只能到4,大于4的被限制为4字节对齐,而且默认是4字节对齐,但是
如果max(struct.member)<4 则按正常对齐规则

stackoverflow 好文

The answer to your question is no. The aligned attribute does not change the sizes of variables it is applied to, but the situation is slightly different for structure members. To quote the manual,

aligned (alignment)

This attribute specifies a minimum alignment for the variable or structure field, measured in bytes. For example, the declaration:
int x __attribute__ ((aligned (16))) = 0;
causes the compiler to allocate the global variable x on a 16-byte boundary.

and,

packed

The packed attribute specifies that a variable or structure field should have the smallest possible alignment — one byte for a variable, and one bit for a field, unless you specify a larger value with the aligned attribute.
Here is a structure in which the field x is packed, so that it immediately follows a:

    struct foo {
        char a;
        int x[2] __attribute__ ((packed));
    };

Note that the aligned attribute may change the memory layout of structures, by inserting padding between members. Subsequently, the size of the structure will change. For instance:

struct t {
    uint8_t  a __attribute__((aligned(16))); /* one byte plus 15 as padding here */
    uint16_t b __attribute__((aligned(16)));
};

would lead to 15 bytes of padding after a whereas the default alignment for the target architecture might have resulted in less. If you specified the packed attribute for the structure and lost the aligned attributes the structure would have a size of 3 bytes. Here's an illustration of how the memory layout of a structure might look like in each case.

struct t with no attributes and default alignment on 8-byte boundary:

+-+-------+--+-------+
|a|       |bb|       |
+-+-------+--+-------+

struct t when a and b are aligned on 16-byte boundaries:

+-+---------------+--+---------------+
|a|    padding    |bb|    padding    |
+-+---------------+--+---------------+

struct t when a and b have no alignment restrictions and t is packed:

+-+--+
|a|bb|
+-+--+
posted @ 2015-07-10 13:52  Lcnoctave  阅读(613)  评论(0编辑  收藏  举报