宏offsetof分析
1、前言
在C语言的结构体中,由于字节对齐的问题,所以成员的地址并不能直接根据数据类型的大小进行计算,使用宏offsetof可以获得结构体成员相对于结构体首地址的字节偏移量。
2、offsetof宏实现
在C标准库中offsetof的声明如下,需要包含头文件<stddef.h>:
size_t offsetof(type, member);
参数:
type:结构体类型
member:结构体中成员的名称
返回值:
返回类型为size_t的值,表示type中member的偏移量
该宏在Linux内核源码内的实现如下:
#define offsetof(TYPE, MEMBER) ((size_t)&((TYPE *)0)->MEMBER)
通过上面这个宏为什么能获取到结构体某个成员的偏移地址呢?首先,偏移地址的计算方法为:
当前的成员地址-结构体首地址=偏移地址
在offsetof宏中,将0地址强制转换成了(TYPE *)类型,也就是说结构体的首地址为0,所以根据偏移地址计算方法,可以知道当前成员的地址也就等于偏移地址,所以宏offsetof将成员的地址取出并返回,获得的就是某个成员的偏移地址了,返回值为size_t类型,需要引起一定的注意。
3、实例
下面是一个offsetof的使用实例,代码如下所示:
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h> struct s {
int i;
char c;
double d;
char a[];
}; int main(int argc, char *argv[])
{
printf("sizeof(struct s)=%zd\n", sizeof(struct s));
printf("offsets: i=%zd; c=%zd; d=%zd; a=%zd.\n",
offsetof(struct s, i), offsetof(struct s, c),
offsetof(struct s, d), offsetof(struct s, a)); exit(EXIT_SUCCESS);
}
使用gcc编译后运行结果如下所示:
由于字节对齐的原因,所以结构体s的大小为16个字节,假设结构体首地址从0开始,由于int类型占用4字节,所以地址0到3为变量i所用,char类型占用1字节,地址4为变量c所用,由于需要字节对齐并且double类型的开始地址必须是8的整数倍,因此地址5到7被填充,double类型占用8字节,地址8到15被变量d所用,a的地址则从地址16开始,因此,通过宏offsetof便可以得到结构体成员的偏移地址。
参考:
https://www.runoob.com/cprogramming/c-macro-offsetof.html
https://www.cnblogs.com/litifeng/p/7685378.html
宏offsetof分析的更多相关文章
- container_of宏定义分析---linux内核
问题:如何通过结构中的某个变量获取结构本身的指针??? 关于container_of宏定义在[include/linux/kernel.h]中:/*_** container_of - cast a ...
- 剖析linux内核中的宏-----------offsetof
offsetof用于计算TYPE结构体中MEMBER成员的偏移位置. #ifndef offsetof#define offsetof(TYPE, MEMBER) ((size_t) &((T ...
- linux内核container_of宏定义分析
看见一个哥们分析container_of很好,转来留给自己看 一.#define offsetof(TYPE, MEMBER) ((size_t) & ((TYPE *)0)->MEMB ...
- 《linux 内核全然剖析》 笔记 CODE_SPACE 宏定义分析
在memory.c里面.遇到一个宏定义,例如以下: #define CODE_SPACE(addr) ((((addr)+4095)&~4095) < \ current->sta ...
- 宏_CRTIMP分析
CRTIMP是C run time implement的简写,C运行库的实现的意思. 作为用户代码,不应该使用这个东西. 该参数决定 运行时 到底用 动态链接库 还是静态链接 #ifndef _CRT ...
- C语言-宏定义与使用分析
1.C语言中的宏定义 #define是预处理器处理的单元实体之— #define定义的宏可以出现在程序的任意位置 #define定义之后的代码都可以使用这个宏 2.定义宏常量 #define定义的宏常 ...
- offsetof宏---个人笔记
标准库里面提供的offsetof(t,m)宏,用来计算两个变量在内存中的地址偏移量 #include <stdio.h>//原型: #define offsetof(TYPE, MEMBE ...
- 【宏蛋白组】iMetaLab平台分析肠道宏蛋白质组数据
目录 一.iMetaLab简介 二.内置工具与模块 1. Data Processing module 2. Functional Analysis 3. R Developing environme ...
- C语言笔记(结构体与offsetof、container_of之前的关系)
关于结构体学习,需要了解:结构体的定义和使用.内存对齐.结构体指针.得到结构体元素的偏移量(offsetof宏实现) 一.复习结构体的基本定义和使用 typedef struct mystruct { ...
随机推荐
- asp.net core流式上传大文件
asp.net core流式上传大文件 首先需要明确一点就是使用流式上传和使用IFormFile在效率上没有太大的差异,IFormFile的缺点主要是客户端上传过来的文件首先会缓存在服务器内存中,任何 ...
- Centos7 Putty SSH密钥登录
在本地电脑打开PuTTYgen程序,点击Generate生成密钥,可以再设置一层密码,保存公钥和私钥到本地文件,保存好,最好多处备份 先用密码登录远程Centos vim ~/.ssh/authori ...
- es6中的arrowfunction
es6新增箭头函数,主要解决了以下几点问题 函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象. 不可以当作构造函数,也就是说,不可以使用new命令,否则会抛出一个错误. 不可以使用 ...
- 【MySQL】备份和恢复
语法 mysqldump -uslave -p -h127.0.0.1 --single-transaction --set-gtid-purged=OFF database1 table1 tabl ...
- itextpdf5生成document生成pdf的简单dome
package dbzx.pdf; import java.io.FileNotFoundException; import java.io.FileOutputStream; import org. ...
- 01、Linux基础命令
linux 一些主要目录的认识: /bin 二进制可执行命令 /boot 存放系统引导文件,如 内核.grub 等 /dev 设备文件 /etc 系统配置目录 /home 普通用户家目录 /lib 系 ...
- SpringBoot配置多注册中心(yml,properties)
dubbo-2.6.6 dubbo.config.multiple=true dubbo.registries.z1.timeout = 5000 dubbo.registries.z1. ...
- 大数据技术原理与应用:【第二讲】大数据处理架构Hadoop
2.1 Hadoop概论 创始人:Doug Cutting 1.简介: 开源免费; 操作简单,极大降低使用的复杂性; Hadoop是Java开发的; 在Hadoop上开发应用支持多种编程语言.不限于J ...
- 数据结构篇——字典树(trie树)
引入 现在有这样一个问题, 给出\(n\)个单词和\(m\)个询问,每次询问一个单词,回答这个单词是否在单词表中出现过. 好像还行,用 map<string,bool> ,几行就完事了. ...
- HDU6583:Typewriter(dp+后缀自动机)
传送门 题意: 给出\(p,q\),现在要你生成一个字符串\(s\). 你可以进行两种操作:一种是花费\(p\)的代价随意在后面添加一个字符,另一种是花费\(q\)的代价可以随意赋值前面的一个子串. ...