结构体之offsetof宏详细解析

2023-05-16

1、#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE*)0)->MEMBER)     (include/linux/stddef.h)

1.1 功能:

返回结构体TYPE中MEMBER成员相对于结构体首地址的偏移量,以字节为单位。

1.2 解析:

此类复杂表达式的解析应该采用从内向外、逐层理解的方式。

首先,(TYPE *)0表示将数字0强制类型转换为TYPE类型(TYPE为结构体类型)的指针。因此这里的0代表内存地址0,即我们认为内存地址0开始的sizeof(TYPE)个字节内存储的是一个TYPE类型的变量。

然后,((TYPE *)0)->MEMBER 得到该结构体变量中的MEMBER成员变量,

而 &(((TYPE*)0)->MEMBER) 使用取地址符&取得了MEMBER成员变量的地址,(size_t)加在前面表示将MEMBER成员变量的地址强制类型转换为size_t(即unsigned int),并将结果作为宏的返回值。

可见,offsetof宏返回的是MEMBER成员在内存中的实际地址。又因为整个结构体的起始地址是0,因此MEMBER成员的实际地址在数值上就等于MEMBER成员相对于结构体首地址的偏移量。

1.3 扩展思考:

1.3.1 使用offsetof宏会影响内存0地址处的值吗?

答案是不会,从1.3.2可知offsetof宏的运算是在C编译器编译时完成的,因此内存的0地址在机器指令中根本未被操作,当然不会影响其值了。

1.3.2offsetof宏返回的MEMBER相对于结构体首地址的偏移量是如何得到的?->符号如何能正确寻址到结构体中某个成员变量?

想探究struct如何通过->精确寻址每一个成员,最好的办法就是将C代码汇编为.S的汇编语言代码,通过观察汇编代码可以看到C编译器对代码处理的具体细节。我们的示例代码如下:

 

#include"stdio.h"

 

#definemyoffsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)

 

typedefstruct st

{

    int a;

    int c;     //将该行加上或去掉,对比得到的汇编代码的差别

    short d;   //将该行加上或去掉,对比得到的汇编代码的差别

    char b;

}st;

 

intgetoffsetof(void)

{

    return myoffsetof(struct st, b);

}

将以上代码保存为offsetof.c,并且使用arm-linux-gcc offsetof.c –S执行汇编,则会得到offsetof.s文件,内容如下:

        .file  "offsetof.c"

        .text

        .align 2

        .global getoffsetof

        .type  getoffsetof, %function

getoffsetof:

        @ Function supports interworking.

        @ args = 0, pretend = 0, frame = 0

        @ frame_needed = 1, uses_anonymous_args= 0

        mov    ip, sp        // 这三行

        stmfd  sp!, {fp, ip, lr, pc}   // 是函数

        sub    fp, ip, #4           // 栈帧保存

        mov    r3, #10          // #10即是offsetof宏计算得到的值

        mov    r0, r3        // 将返回值置于R0中

        sub    sp, fp, #12      // 函数栈帧

        ldmfd  sp, {fp, sp, lr}    // 恢复

        bx     lr            // 函数返回

        .size  getoffsetof, .-getoffsetof

        .ident "GCC: (GNU) 4.1.2"

以上汇编代码中mov r3, #10一句可以看出,offsetof宏计算member的偏移量是C编译器在编译阶段完成的,而并不需要CPU在运行时去计算得出。

可以尝试着更改struct st中成员b之前的成员,然后再次汇编,对比汇编后代码的不同,以此来验证我们的推论。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

结构体之offsetof宏详细解析 的相关文章

  • BGP边界网关协议基础知识点

    BGP xff1a 边界网关协议 AS 自治系统 由单一机构或组织管理的一系列IP网络机器设备的集合 网络范围太大 xff0c 协议跑不过来 xff0c 需要进行划分自治管理 为了方便区分和标定不同AS xff0c 我们给每个自治系统设计了
  • 温湿度传感器SHTC3驱动开发(一)小白也能轻松理解

    一 首先了解设备硬件原理图 首先在公司干活 xff0c 要你开发一个设备驱动 xff0c 那你的老大必须得给你的东西如下 xff1a 开发板主板硬件原理图驱动设备的硬件原理图驱动的设备的数据手册 xff08 datasheet xff09
  • nodejs的版本管理工具(nvm)

    1 nvm是什么 nvm全名node js version management xff0c 顾名思义是一个nodejs的版本管理工具 为了解决node各种版本存在不兼容现象 nvm是让你在同一台机器上安装和切换不同版本的node的工具 x
  • A变为a和a的ASCII值

    span class hljs comment include lt stdio h gt span main char ch span class hljs keyword printf span span class hljs stri
  • 机器学习python Kmeans聚类

    import numpy as np import matplotlib pyplot as plt import pandas as pd from sklearn cluster import KMeans from sklearn i
  • 为wget命令设置代理

    实验环境 xff1a ubuntu 12 04 LTS goagent 方法一 在环境变量中设置代理 export http proxy 61 http 127 0 0 1 8087 方法二 使用配置文件 为wget使用代理 xff0c 可
  • ubuntu14.04安裝numpy,scipy

    在windows下搞python xff0c 实在出错太多 xff0c 就安装了双系统 xff0c 在ubuntu下试着学习一下 xff0c 我的ubuntu版本为ubuntu14 04 以前不知道python的这些包之间是有依赖关系的 x
  • STM32的中断体系和FSMC控制LCD-第3季第7部分视频课程-朱有鹏-专题视频课程

    STM32的中断体系和FSMC控制LCD 第3季第7部分视频课程 861人已学习 课程介绍 本课程是 朱有鹏老师单片机完全学习系列课程 第3季第7个课程 xff0c 本课程详细讲解STM32的外部中断和FSMC模块 xff0c 这两个模块都
  • ubuntu加入Windows的AD域(使用Samba和Winbind的方式)

    ubuntu加入Windows的AD域 Integrate Ubuntu 16 04 to AD as a Domain Member with Samba and Winbind Part 8 Step 1 Initial Configu
  • XTU 1262 Fish(优先队列+贪心)

    钓鱼 http 202 197 224 59 exam index php problem read id 1262 题目描述 小明很喜欢钓鱼 xff0c 现在有n个池塘可以钓鱼 xff0c 第i个池塘首次内能钓到ai条鱼 第i个池塘如果被
  • webpack开发调试模式devtool

    devtool 有7种模式 eval 文档上解释的很明白 xff0c 每个模块都封装到 eval 包裹起来 xff0c 并在后面添加 sourceURL source map 这是最原始的 source map 实现方式 xff0c 其实现
  • HDFS 集成 Kerberos

    本文主要记录 CDH Hadoop 集群上配置 HDFS 集成 Kerberos 的过程 xff0c 包括 Kerberos 的安装和 Hadoop 相关配置修改说明 注意 xff1a 下面第一 二部分内容 xff0c 摘抄自 Hadoop
  • html实现自动清理js、css文件的缓存

    方法如下 xff1a 1 手动清除浏览器缓存 xff1b 2 添加版本号 方法一 xff1a 可以通过js自动给html添加版本号 lt script type 61 34 text javascript 34 gt document wr
  • 虚拟机在nat模式下无法连接网络

    问题导入 在vmware下使用虚拟机由于某些原因设置了静态IP但是在后续的使用发现无法创建新的ssh连接 xff08 之前建立过连接并保存了密钥的仍可连接 xff09 xff0c 同时发现了主机网络可以正常ping通虚拟机的网络 xff0c
  • 74HC573芯片简介

    芯片缺口方向 为正 xff0c 然后左上往下排列 xff0c 最后一个是GND xff0c 然后 向右 xff0c 再向右上 xff0c 右上角为Vcc GND 和Vcc成对角线 xff0c 是为了防止发生短路 LE xff1a latch
  • c语言中返回值为char*的情况分析

    容易出错的地方在于 xff1a 指针作为返回值 xff0c 但是指针指向的内存单元在函数返回后 xff0c 内存单元释放了 xff0c 这样就导致了指针成了野指针了 xff01 xff01 xff01 这样会报错 xff0c 因为str数组
  • 网线水晶头接法分两种教程

    转载 xff1a https blog csdn net VickHUC article details 90081813 我们家里如果要用网线的话 xff0c 其实是可以自己接水晶头的 xff0c 当然你得有一个叫压线钳的工具 xff0c
  • STM32的定时器和DS18B20调试-第3季第8部分视频课程-朱有鹏-专题视频课程

    STM32的定时器和DS18B20调试 第3季第8部分视频课程 975人已学习 课程介绍 本课程是 朱有鹏老师单片机完全学习系列课程 第3季第8个课程 xff0c 本课程详细讲解STM32的定时器 xff0c 尤其是SYSTICK定时器和通
  • c语言/c++中指针的动态初始化及释放

    提醒 xff1a 使用指针最容易犯得错误是 xff0c 没有初始化就直接操作 xff01 xff01 xff01 1 指针的初始化 释放 1 xff09 指针指向一个内存单元 i c语言 xff1a char ch 61 char mall
  • c语言函数参数为指针的情况分析

    指针取 解引用 表示的是指针所指向内存单元中内容 xff1b 或者理解为该内存空间 指针传递其实也是一种值传递 xff0c 只不过传递的是地址值 xff0c 如果通过该地址取 解引用 xff0c 是可以改变形参指针的原值的 xff0c 但如

随机推荐

  • MATLAB快速傅里叶变换(fft)函数详解

    转载 xff1a https blog csdn net me4weizhen article details 53688848 定义 xff1a The 39 i 39 in the 39 Nth root of unity 39 是虚数
  • C++中substr()函数用法详解

    定义 substr 是C 43 43 语言函数 xff0c 主要功能是复制子字符串 xff0c 要求从指定位置开始 xff0c 并具有指定的长度 如果没有指定长度 Count或 Count 43 Off超出了源字符串的长度 xff0c 则子
  • 101、104规约解析

    转载 xff1a 电网101 104规约解析 xff08 Java xff09 张二狗和苗翠花的博客 CSDN博客 iec101 java 1 前言 最近在研究广东电网的101与104规约 xff0c 也就是DL T634 5101 200
  • 第一范式(1NF)、第二范式(2NF)和第三范式(3NF)

    第一范式 xff08 1NF xff09 xff1a 列1唯一确定列2 列3 列4 xff0c 即列2 列3 列4 不能再分裂出其它列 假设有关系模式列1 订单名 列2 商品 一个订单下可以有多个商品 xff0c 即列2 商品可以分裂成商品
  • 关于 傅里叶变换 的一些理解(通俗版)

    什么是傅里叶变换 xff1f 对随时间变化的曲线 xff0c 不再从时间轴上去看他的变化 xff0c 而是消去时间因子 xff0c 从出现的频率上来分析他的变化情况 例如 xff1a 股市变化曲线是随时间变化的曲线 xff0c 而通过傅里叶
  • excel取消多行隐藏

    同时取消多行隐藏 xff0c 需要选中隐藏行的上一行和下一行 xff0c 然后右键点击取消隐藏行
  • 双面打印说明

    长边翻页表示以A4纸较长的边翻页 xff0c 类似A4纸张大小的书本的翻页 xff0c 短边翻页则是以较短的边翻页 xff1b 长边翻页是从右往左翻页 xff0c 短边翻页是从下往上翻页 xff0c 翻页后文字观看方向不同 xff1b 长边
  • Segment routing分段路由

    为了解决传统IP转发和MPLS转发的问题 xff0c 业界提出了SR xff08 segment routing xff0c 分段路由 xff09 SR的转发机制有很大改进 xff0c 主要体现在以下几个方面 1 基于现有协议进行扩展 xf
  • mount: RPC: Unable to receive; errno = No route to host

    环境 xff1a gec2440开发板 VMware8 0 43 Ubuntu10 04 uboot xff0c kernel xff0c rootfs都是之前做好的 xff0c 调试驱动都反复用过很多次 今天只是搬了台电脑 xff0c 换
  • 实现Charles+Postern抓包

    实现Charles 43 Postern抓包 在实际抓手机App包场景中 有很多种方案 经典的就是Fiddler 但是Fiddler会有一个问题 如果App设置了不走代理这个选项 那Fiddler就不行了 xff0c 比如说大众点评 xff
  • STM32学习—systick系统定时器

    SysTick定时器配置步骤 SysTick定时器的操作可以分为 4 步 xff1a xff08 1 xff09 设置SysTick定时器的时钟源 xff08 2 xff09 设置SysTick定时器的重装初始值 xff08 如果要使用中断
  • Mac 关闭设置系统升级红点

    关闭系统更新提醒红点 xff1a 在终端输入 xff1a defaults write com apple systempreferences AttentionPrefBundleIDs 0 killall dock
  • 图像特征提取算法之Haar特征原理(一)

    文章目录 笔记截图问题积分图例子结论 笔记截图 用白色的特征值之和 黑色的特征值之和 61 这一个区域的特征值 你也可以理解为用卷积进行提取 xff0c 白色的区域为1 黑色的为 1 xff08 邪恶的黑色 xff09 然后进行相加既可以得
  • CAS方式实现单点登录

    单点登录 xff0c 英文是 Single Sign On xff0c 缩写为 SSO 多个站点 192 168 1 20X 共用一台认证授权服务器 192 168 1 110 xff0c 用户数据库和认证授权模块共用 用户经由其中任何一个
  • 双系统重装Ubuntu经验分享

    真的很喜欢ubuntu 但又没有恒心把它学通透 xff0c 毕竟不是相关专业 第一次重装是因为没多少经验 xff0c 安装qqforlinux的时候多了两个东西 xff0c 还自己生成了快捷方式 xff0c 就想点开看看是啥 xff0c 结
  • PCL三维点云拼接融合

    1 PCL三维点云拼接融合技术 2 PCL系列 拼接两个点云
  • ubuntu20版本忘记或重置密码的问题

    前段时间把ubuntu密码忘了 xff0c 进不去并且有些需要密码权限的功能也用不了 xff0c 在网上搜了一大堆 xff0c 都是什么从开始就摁shift或Esc xff0c 好家伙摁烂了也不行啊 解决如下 xff1a 首先 xff0c
  • 程序员申请加班调休被HR拒绝:996是行规,不想加班就滚?

    现如今 xff0c 很多公司为了不给员工加班费 xff0c 一般都会允许他们进行调休 也就是你加班了多少个小时 xff0c 等项目不忙的时候 xff0c 你们可以选择多休息几天 公司的这种做法 xff0c 大多数员工还是能接受的 xff0c
  • 博士生如何进行文献阅读和文献整理?

    一 阅读文献之前 先了解写文章的规则 SCI的架构 TITLE ABSTRACT main message INTRODUCTION why did you do this job METHODS how did you do it RES
  • 结构体之offsetof宏详细解析

    1 define offsetof TYPE MEMBER size t amp TYPE 0 gt MEMBER include linux stddef h 1 1 功能 xff1a 返回结构体TYPE中MEMBER成员相对于结构体首地