zoukankan      html  css  js  c++  java
  • Linux下的两个经典宏定义

    本文首先介绍Linux下的经典宏定义,感受极客的智慧,然后根据该经典定义为下篇博客作铺垫。

    offsetof宏

    定义:

    // 获得结构体(TYPE)的变量成员(MEMBER)在此结构体中的偏移量。
    #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)


    说明:获得结构体(TYPE)的变量成员(MEMBER)在此结构体中的偏移量。
    1.( (TYPE *)0 ) 将零转型为TYPE类型指针,即TYPE类型的指针的地址是0。
    2.((TYPE *)0)->MEMBER     访问结构中的数据成员。
    3.&( ( (TYPE *)0 )->MEMBER )   取出数据成员的地址。由于TYPE的地址是0,这里获取到的地址就是相对MEMBER在TYPE中的偏移。
    4.(size_t)(&(((TYPE*)0)->MEMBER))  结果转换类型。对于32位系统而言,size_t是unsigned int类型;对于64位系统而言,size_t是unsigned long类型。

    使用示例:

    struct student
    {
    	char gender;
    	int id;
    	int age;
    	char name[20];
    };
    
    
    int _tmain(int argc, _TCHAR* argv[])
    {
    	int gender_offset, id_offset, age_offset, name_offset;
    
    
    	gender_offset = offsetof(struct student, gender);
    	id_offset = offsetof(struct student, id);
    	age_offset = offsetof(struct student, age);
    	name_offset = offsetof(struct student, name);
    
    
    	printf("gender_offset = %d
    ", gender_offset);
    	printf("id_offset = %d
    ", id_offset);
    	printf("age_offset = %d
    ", age_offset);
    	printf("name_offset = %d
    ", name_offset);
    
    
    	system("pause");
    	return 0;
    }
    //结果:
    /*
    gender_offset = 0 
    id_offset = 4 //字节对其
    age_offset = 8
    name_offset = 12
    */

    offsetof图解

    TYPE是结构体,它代表"整体";而MEMBER是成员,它是整体中的某一部分。


    container_of宏

    定义:

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


    说明:根据"结构体(type)变量"中的"域成员变量(member)的指针(ptr)"来获取指向整个结构体变量的指针。
    1. typeof( ( (type *)0)->member )     取出member成员的变量类型。
    2.const typeof( ((type *)0)->member ) *__mptr = (ptr)    定义变量__mptr指针,并将ptr赋值给__mptr。经过这一步,__mptr为member数据类型的常量指针,其指向ptr所指向的地址。
    3. (char *)__mptr    将__mptr转换为字节型指针。
    4. offsetof(type,member))    就是获取"member成员"在"结构体type"中的位置偏移。
    5. (char *)__mptr - offsetof(type,member))    就是用来获取"结构体type"的指针的起始地址(为char *型指针)。
    6.(type *)( (char *)__mptr - offsetof(type,member) )    就是将"char *类型的结构体type的指针"转换为"type *类型的结构体type的指针"。
    7.反斜杠“/”表示行连接


    使用示例:

    注:本例中的addressof宏定义与上面的宏定义相同,只是一个改写。

    // 获得结构体(TYPE)的变量成员(MEMBER)在此结构体中的偏移量。
    #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
    /*根据"结构体(type)变量"中的"域成员变量(member)的指针(ptr)"来获取指向整个结构体变量的指针*/
    #define addressof(PT,TYPE,MEMBER) ((TYPE *)((char *)(PT) - offsetof(TYPE,MEMBER)))
    
    
    struct student
    {
    	char gender;
    	int id;
    	int age;
    	char name[20];
    };
    
    
    void main()
    {
    	struct student stu;
    	struct student *pstu;
    
    
    	stu.gender = '1';
    	stu.id = 9527;
    	stu.age = 24;
    	strcpy(stu.name, "zhouxingxing");
    
    
    	// 根据"id地址" 获取 "结构体的地址"。
    	pstu = addressof(&(stu.id), struct student, id);
    
    
    	// 根据获取到的结构体student的地址,访问其它成员
    	printf("gender= %c
    ", pstu->gender);
    	printf("age= %d
    ", pstu->age);
    	printf("name= %s
    ", pstu->name);
    }
    /*结果
    gender= 1
    age= 24
    name= zhouxingxinggender= 1
    age= 24
    name= zhouxingxing
    */

    container_of图解

    type是结构体,它代表"整体";而member是成员,它是整体中的某一部分,而且member的地址是已知的。

    最后,可以想想这个宏都有哪些用途。

    生命不止,奋斗不息!
  • 相关阅读:
    二分法检索数组
    Linux安装CDH
    myeclipse操作hdfs
    Linux安装hbase
    Linux安装zookeeper
    Linux安装msql
    fluem全分布环境搭建
    bash: jps: 未找到命令...
    自动化项目Jenkins持续集成
    linux卸载mysql====安装新的虚拟机 自带的基本都要卸载!? mysql tomcat java Python可以不用卸载
  • 原文地址:https://www.cnblogs.com/huzongzhe/p/6735164.html
Copyright © 2011-2022 走看看