C语言学习笔记 _内存对齐大小端共用体等

C语言学习笔记 _内存对齐大小端共用体等

offsetof宏

offset宏返回的是member元素相对于整个结构体变量的首地址的偏移量,类型是int:

#define offsetof(TYPE, MEMBER) ((int) &((TYPE *)0)->MEMBER)

这个宏的原理是,在地址0处虚拟此结构体,然后用地址0的结构体指针获得member元素的地址,那么此地址的数值相当于是偏移量,因为从0出发的地址,偏移量就是其本身;

container_of宏

container_of宏返回指向整个结构体变量的指针,类型是(type *);

ptr是指向结构体元素member的指针,type是结构体类型,member是结构体中一个元素;

#define container_of(ptr, type, member) ({	\
	const typeof(((type *)0)->member) * __mptr = (ptr);	\
	(type *)((char *)__mptr - offsetof(type, member)); })

此宏通过获取member的数据类型,和其地址ptr,定义与member相同类型的变量__mptr,注意代码中((type *)0)->member)只是为了定义一个结构体以获得member的变量类型,(之所以要这么复杂定义这个指针,是为了不改变ptr这个源指针)。最后利用此地址减去偏移量就可以得到结构体的地址了;

通过此宏,可以从一个元素的指针的指针,得到整个结构体变量的指针,结合offset可以得到所有元素的指针;

typeof关键字的作用是:得到变量的数据类型;

共用体union

共用体方式的使用方法和结构体基本一致;但是含义完全不同;

共用体就是对同一块内存中存储的二进制不同的理解方式;也就是申明同一块内存的不同数据类型;

sizeof共用体,得到的是各元素中占用内存最大的元素的大小;

共用体方法可以用指针加强制类型转换来替代,如下所示:

union student{
   int a;
   float b;
};

// 共用体方式
union test t1;
t1.a = 1123477881;
printf("value = %f.\n", t1.b);

// 指针方式
int a = 1123477881;
printf("point mode: %f.\n", *(float *)&a);

大小端模式

这是两种数据在内存种的存储方式:

大端模式:数据高位存放于低地址,低位存放于高地址;

小端模式:数据高位存放于高地址,低位存放于低地址;

当不确定大小端模式的时候,通过union来判断大小端模式:

union un {
  int a;
  char b;
};

// 判断函数
int check(void) {
	union un u1;
    u1.a = 1;
    return u1.b;
}

// 输出1则为小端模式,输出0则为大端模式
printf("mode is %d.\n", check());

通过union方式判断大小端模式的依据是,int类型占用四字节,数据为00 00 00 01:

大端模式下存放方式为:00 00 00 01;小端模式下存放的方式为:01 00 00 00;

那么当把这段内存按照char读取的时候只会读取低地址的一个字节,于是大端模式下为0,小端模式为1;

另外,位与运算、移位、强制类型转换不能用于检测大小端,因为编译器对其做了封装。

枚举

enum week {
	SUM,	
    MON,
    TUE,
};

enum value {
	TRUE = 12,	  
    FALSE = 13,
};

枚举相当于用符号代替数字,作用于全局,可直接使用。

如果只声明符号,默认从0开始,也可以声明符号与数字。

posted @ 2020-07-07 16:44  樱花小猪  阅读(192)  评论(2编辑  收藏  举报