offsetof

本文深入解析了C语言中结构体的内存布局,包括如何获取结构体内成员的地址和偏移量,并通过示例代码进行演示。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

#include <stdio.h>
#include <stdlib.h>

struct foobar{
	unsigned int foo;
	char bar;
	char boo;
};

int main(int argc, char** argv){

	struct foobar tmp;

	printf("address of &tmp is= %p\n\n", &tmp);
	printf("address of tmp->foo= %p \t offset of tmp->foo= %lu\n", &tmp.foo, (unsigned long) &((struct foobar *)0)->foo);
	printf("address of tmp->bar= %p \t offset of tmp->bar= %lu\n", &tmp.bar, (unsigned long) &((struct foobar *)0)->bar);
	printf("address of tmp->boo= %p \t offset of tmp->boo= %lu\n\n", &tmp.boo, (unsigned long) &((struct foobar *)0)->boo);

	printf("computed address of &tmp using:\n");
	printf("\taddress and offset of tmp->foo= %p\n",
	      (struct foobar *) (((char *) &tmp.foo) - ((unsigned long) &((struct foobar *)0)->foo)));
	printf("\taddress and offset of tmp->bar= %p\n",
	      (struct foobar *) (((char *) &tmp.bar) - ((unsigned long) &((struct foobar *)0)->bar)));
	printf("\taddress and offset of tmp->boo= %p\n",
	      (struct foobar *) (((char *) &tmp.boo) - ((unsigned long) &((struct foobar *)0)->boo)));

	return 0;
}

same as 
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
/**
 * container_of - cast a member of a structure out to the containing structure
 * @ptr:        the pointer to the member.
 * @type:       the type of the container struct this is embedded in.
 * @member:     the name of the member within the struct.
 *
 */  
#define container_of(ptr, type, member) ({                      \   
        const typeof( ((type *)0)->member ) *__mptr = (ptr);    \   
        (type *)( (char *)__mptr - offsetof(type,member) );})


资源下载链接为: https://pan.quark.cn/s/d9ef5828b597 四路20秒声光显示计分抢答器Multisim14仿真源文件+设计文档资料摘要 数字抢答器由主体电路与扩展电路组成。优先编码电路、锁存器、译码电路将参赛队的输入信号在显示器上输出;用控制电路和主持人开关启动报警电路,以上两部分组成主体电路。通过定时电路和译码电路将秒脉冲产生的信号在显示器上输出实现计时功能,构成扩展电路。经过布线、焊接、调试等工作后数字抢答器成形。关键字:开关阵列电路;触发锁存电路;解锁电路;编码电路;显示电路 一、设计目的 本设计是利用已学过的数电知识,设计的4人抢答器。(1)重温自己已学过的数电知识;(2)掌握数字集成电路的设计方法和原理;(3)通过完成该设计任务掌握实际问题的逻辑分析,学会对实际问题进行逻辑状态分配、化简;(4)掌握数字电路各部分电路与总体电路的设计、调试、模拟仿真方法。 二、整体设计 (一)设计任务与要求: 抢答器同时供4名选手或4个代表队比赛,分别用4个按钮S0 ~ S3表示。 设置一个系统清除和抢答控制开关S,该开关由主持人控制。 抢答器具有锁存与显示功能。即选手按动按钮,锁存相应的编号,并在LED数码管上显示,同时扬声器发出报警声响提示。选手抢答实行优先锁存,优先抢答选手的编号一直保持到主持人将系统清除为止。 参赛选手在设定的时间内进行抢答,抢答有效,定时器停止工作,显示器上显示选手的编号和抢答的时间,并保持到主持人将系统清除为止。 如果定时时间已到,无人抢答,本次抢答无效。 (二)设计原理与参考电路 抢答器的组成框图如下图所示。它主要由开关阵列电路、触发锁存电路、解锁电路、编码电路和显示电路等几部分组成。
### 宏定义 `offsetof` 的用法与含义 宏定义 `offsetof` 是 C 和 C++ 中用于计算结构体成员相对于结构体起始地址的偏移量的一种工具。它返回的结果是以字节为单位的偏移量,通常用于内存操作或低级编程场景中[^1]。 在标准头文件 `<stddef.h>` 中,`offsetof` 的定义如下: ```cpp #define offsetof(s, m) (size_t)&(((s*)0)->m) ``` #### 宏定义解释 - `(s*)0`:将 0 强制转换为类型 `s` 的指针,表示一个虚拟的结构体实例。 - `->m`:访问该虚拟结构体中的成员 `m`。 - `(size_t)&`:取成员 `m` 的地址,并将其转换为 `size_t` 类型,从而得到以字节为单位的偏移量。 这种实现方式通过假设结构体起始地址为 0 来计算成员相对于结构体起始位置的偏移量。需要注意的是,这种方式不会实际分配内存,因此不会引发运行时错误[^2]。 #### 示例代码 以下是一个使用 `offsetof` 的示例,展示如何计算结构体成员的偏移量: ```c #include <stdio.h> #include <stddef.h> struct Example { char a; // 偏移量 0 int b; // 偏移量 4(假设存在 3 字节对齐填充) double c; // 偏移量 8 }; int main() { printf("Offset of 'a': %zu\n", offsetof(struct Example, a)); // 输出 0 printf("Offset of 'b': %zu\n", offsetof(struct Example, b)); // 输出 4 printf("Offset of 'c': %zu\n", offsetof(struct Example, c)); // 输出 8 return 0; } ``` #### 注意事项 1. **内存对齐**:由于编译器可能会对结构体成员进行内存对齐处理,实际偏移量可能与成员顺序和大小不完全一致。例如,在上述示例中,`char a` 后可能有 3 字节的填充以满足 `int b` 的对齐要求[^3]。 2. **安全性**:`offsetof` 不会检查结构体的有效性或成员是否存在,因此如果使用不当可能导致未定义行为[^4]。 3. **跨平台兼容性**:不同平台和编译器可能有不同的内存对齐规则,因此在跨平台开发中需特别注意[^5]。 #### 自定义实现 `offsetof` 如果需要手动实现 `offsetof`,可以参考以下代码: ```c #define MY_OFFSETOF(s, m) ((size_t)((char*)&((s*)0)->m - (char*)0)) ``` 此实现与标准定义类似,但显式地计算了地址差值。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值