转自:http://www.linuxidc.com/Linux/2015-07/120014.htm

本文首先介绍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\n", gender_offset);
 printf("id_offset = %d\n", id_offset);
 printf("age_offset = %d\n", age_offset);
 printf("name_offset = %d\n", 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.反斜杠“/”表示行连接

更多详情见请继续阅读下一页的精彩内容http://www.linuxidc.com/Linux/2015-07/120014p2.htm

Linux下的两个经典宏定义【转】的更多相关文章

  1. Linux下的两个经典宏定义 转

    http://www.linuxidc.com/Linux/2016-08/134481.htm http://www.linuxidc.com/Linux/2013-01/78003.htm htt ...

  2. Linux中的两个经典宏定义:获取结构体成员地址,根据成员地址获得结构体地址;Linux中双向链表的经典实现。

    倘若你查看过Linux Kernel的源码,那么你对 offsetof 和 container_of 这两个宏应该不陌生.这两个宏最初是极客写出的,后来在Linux内核中被推广使用. 1. offse ...

  3. Linux 下启动两个tomcat

    Linux 下启动两个tomcat 闲来无事学习nginx,想要配置个load balance.可是先决条件是:得有两个web容器.两个电脑是不用想了.只能想办法在一个机器上启动两个tomcat.原以 ...

  4. Linux下配置两个或多个Tomcat启动

    Linux下配置两个或多个Tomcat启动 (2012-08-14 11:59:31) 转载▼ 标签: 杂谈 分类: linux_tomcat 步骤如下: (1)修改/etc/profile文件.添加 ...

  5. Linux下的两种磁盘分区工具的使用

    如何使用fdisk和parted分区工具来进行硬盘分区,下面我来说一下在Linux系统中这两种硬盘分区工具的使用方法:     ----------fdisk分区工具----------       ...

  6. Linux下使用两个线程协作完成一个任务的简易实现

    刚解决了之前的那个Linux下Pthread库的问题,这次就来使用两个线程来协作,共同完成一个求和的任务. 打一下基础吧 本次需要使用到的知识点有: lpthread,编译的时候用到,相当于一个声明的 ...

  7. Linux 下的两种分层存储方案

    背景介绍 随着固态存储技术 (SSD),SAS 技术的不断进步和普及,存储介质的种类更加多样,采用不同存储介质和接口的存储设备的性能出现了很大差异.SSD 相较于传统的机械硬盘,由于没有磁盘的机械转动 ...

  8. Linux内核驱动基础(一)常用宏定义【转】

    转自:http://blog.csdn.net/tommy_wxie/article/details/9427081 一: __init和__initdata  : __exit和__exitdata ...

  9. Linux下对比两个文件夹的方法

    最近拿到一份源代码,要命的是这份源代码是浅克隆模式的git包,所以无法完整显示里面的修改的内容. 今天花了一点点时间,找了一个在Linux对比两个文件夹的方法. 其实方法很简单,用meld 去对比两个 ...

随机推荐

  1. 孤荷凌寒自学python第七十六天开始写Python的第一个爬虫6

    孤荷凌寒自学python第七十六天开始写Python的第一个爬虫6 (完整学习过程屏幕记录视频地址在文末) 今天在上一天的基础上继续完成对我的第一个代码程序的书写. 不过由于对python-docx模 ...

  2. Visual Studio 2005安装包

    点击下载

  3. anaconda常用的命令

    常用操作命令: 一.环境操作 1.查看环境管理的全部命令帮助: conda env -h 2.查看当前系统下的环境: conda info -e 3.创建环境: conda create env_na ...

  4. ubuntu中 VI 方向键、删除键问题

    这两天重新装的ubuntu系统,发觉使用VI时,方向键按下去后变成ABCD,删除键无效.网上搜寻一番,应该是VI软件本身的问题,顾卸载重装即可,步骤如下: 1.执行命令 sudo apt-get re ...

  5. Eureka搭建

    Eureka搭建 一.Eureka基本框架搭建 pom.xml文件配置:主要是引入Eureka所依赖的jar包 <?xml version="1.0" encoding=&q ...

  6. mysql创建用户并手授权

    --创建用户CREATE USER 'test'@'%' IDENTIFIED BY 'test'; --授权GRANT ALL ON *.* TO 'test'@'%'; --修改密码SET PAS ...

  7. 学习bash——数据流重定向

    一.概述 1. 数据流 定义:以规定顺序被读取一次的数据序列. 分类:标准输入(stdin).标准输出(stdout)和标准错误输出(stderr). 标准输出:指的是命令执行所回传的正确信息. 标准 ...

  8. NO5——素数筛选

    #include <stdio.h> int main() { ]={}; ;i<=;i++) a[i]=; ;i<=;i++) if(a[i]) ;j+=i) a[j]=; ...

  9. Android Service 服务(三)—— bindService与remoteService

    (转自:http://blog.csdn.net/ithomer/article/details/7366396)   一.bindService简介 bindService是绑定Service服务, ...

  10. PTA实验报告(循环 数组 函数)

    一.循环PTA实验作业 题目一.7-2 求平方根序列前N项和 1.本题PTA提交列表 2.设计思路 本题调用了sqrt数学函数计算平方根,其次只用了一层循环,计算平方根之后使用循环累加计算总和sum. ...