4字节对齐(4的整数倍),就必须是0、4地址,
8字节对齐(8的整数倍),就必须是0、8、16
char c;
int a;
//short d;
}s1;
struct stu2
{
char c;
int a;
//short d;
}s2;
<2>gcc推荐的对齐指令__attribute__((packed)) __attribute__((aligned(n))),在VC中就不行,没有定义这个命令
(1)__attribute__((packed))使用时直接放在要进行内存对齐的类型定义的后面,然后它起作用的范围只有加了这个东西的这一个类型。packed的作用就是取消对齐访问。
(2)__attribute__((aligned(n)))使用时直接放在要进行内存对齐的类型定义的后面,然后它起作用的范围只有加了这个东西的这一个类型。它的作用是让整个结构体变量
整体进行n字节对齐(注意是结构体变量整体n字节对齐,而不是结构体内各元素也要n字节对齐,内部元素按照默认对齐方式)
例子:struct mystruct11
{// 1字节对齐4字节对齐
int a;// 44
char b;// 12(1+1)
short c;// 22
}__attribute__((packed));
typedef struct mystruct111
{// 1字节对齐4字节对齐2字节对齐
int a;// 44 4
char b;// 12(1+1)2
short c;// 22 2
short d;// 2 4(2+2)2
}__attribute__((aligned(1024))) My111;
5.5、offsetof宏:#define offsetof( TYPE, MEMBER) ((int) &((TYPE *)0)->MEMBER)

(1)offsetof宏的作用是:用宏来计算结构体中某个元素和结构体首地址的偏移量(其实质是通过编译器来帮我们计算)。
(2)offsetof宏的原理:我们虚拟一个type类型结构体变量,然后用type.member的方式来访问那个member元素,继而得到member相对于整个变量首地址的偏移量。
(3)学习思路:第一步先学会用offsetof宏,第二步再去理解这个宏的实现原理。
(TYPE *)0 这是一个强制类型转换,把0地址强制类型转换成一个指针,这个指针指向一个TYPE类型的结构体变量。 (实际上这个结构体变量可能不存在,但是只要我不去解引用这个指针就不会出错)。
((TYPE *)0)->MEMBER(TYPE *)0是一个TYPE类型结构体变量的指针,通过指针指针来访问这个结构体变量的member元素,然后对这个元素取地址,又因为
改地址是从0地址开始算的,所以这个地址就是相对起始地址的偏移量。
5.6 container_of宏: #define container_of(ptr, type, member) ({\
const typeof(((type *)0)->member) * __mptr = (ptr);\
(type *)((char *)__mptr - offsetof(type, member)); }) 两条语句;,然后用{ } ,\表示提示编译器本行因为屏幕不够,链接下一行。用#(也就是宏定义)
时,如果本行不够要用 \ 提示编译器接着是下一行的。必须要用 \ ,猜测因为宏定义一行就算结束了。
(1)作用:知道一个结构体中某个元素的指针,反推这个结构体变量的指针。有了container_of宏,我们可以从一个元素的指针得到整个结构体变量的指针,继而得到结构体中其他元素的指针。
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-33816-7.html
猎潜小艇时到还打过几场家门口的海战