C语言应用笔记:获取结构体成员偏移地址

yumo6662小时前技术文章1

在C语言中,获取结构体成员的偏移地址(即成员相对于结构体起始地址的字节偏移量)有两种常用方法:

1. 使用标准库宏 offsetof(推荐)

<stddef.h> 头文件提供了 offsetof 宏,可直接计算成员偏移量:

#include <stdio.h>
 // 包含 offsetof 宏
#include <stddef.h> 
  
typedef struct {
    int a;
    char b;
    float c;
} my_struct;

int main(void) { 
  // 计算成员 c 的偏移量 
  size_t offset = offsetof(my_struct, c);  
  // 输出取决于平台对齐规则 
  printf("offset of 'c' is: %d bytes\n", offset); 
  return 0;
}

2. 手动计算偏移量(理解原理)

通过将结构体地址设为 0,直接获取成员地址作为偏移量:

#include <stdio.h>
 
#define OFFSET_OF(type, member) \
    ((size_t)&(((type *)0)->member))
     
typedef struct {
    int a;
    char b;
    float c;
} my_struct;

int main(void) { 
  // 计算成员 c 的偏移量 
  size_t offset = OFFSET_OF(my_struct, c); 
  // 输出取决于平台对齐规则 
  printf("offset of 'c' is: %d bytes\n", offset); 
  return 0;
}

关键说明:

  1. OFFSET_OF(type, member)原理
  • 将 0 强制转换为结构体指针 (type *)0
  • 通过 -> 访问成员并取地址 &(((type *)0)->member)
  • 转换为 size_t 类型得到偏移量
  1. 内存对齐的影响

结构体成员的实际偏移量受编译器内存对齐规则影响。例如:

struct example { 
  char a; // 偏移 0 
  // 编译器可能插入填充字节(padding) 
  int b; // 偏移通常是 4(32位系统)
};
  1. 使用场景
  • 序列化/反序列化结构体
  • 通过偏移量直接访问内存(如嵌入式开发)
  • 实现通用容器(如 container_of 宏)

输出示例:

在常见 64 位系统上,对于以下结构体:

struct my_struct { 
  int a; // 4 字节(通常对齐到 4 字节边界) 
  char b; // 1 字节 
  float c; // 4 字节(通常对齐到 4 字节边界)
};

输出可能是:

offset of 'c' is: 8 bytes

原因:a 占 4 字节,b 占 1 字节后填充 3 字节以满足 c 的 4 字节对齐。

注意:实际偏移量取决于编译器、平台和编译选项。使用 offsetof 是最安全且可移植的方法。

相关文章

数据结构-位运算_数据结构按位查找

左移( << ):操作数的非0位左移n位,低位补0右移( >> ):操作数的非0位右移n位,高位补0无符号右移( >>> ):正数右移,高位用0补,负数右移,...

PLC的位逻辑运算指令_plc中的位怎么理解

PLC(可编程逻辑控制器)的位指令是针对单个二进制位(0 或 1)进行操作的基础指令,主要用于逻辑控制,是梯形图(LD)编程中最常用的指令类型。以下是 PLC 位指令的核心类别及常用指令:常开常闭输出...

【C语言·015】逗号运算符的求值顺序与返回值规则

很多人第一次看到 , 都把它当“分隔符”:函数实参之间的逗号、初始化列表里的逗号……但在表达式里,, 还有另一个身份——逗号运算符。它既能强制求值顺序,又能控制返回值,是解决副作用与顺序问题的一把小刀...

C 语言指针全解析:从门牌号到内存黑魔法,一文带你彻底搞懂!

很多人一提到 C 语言指针 就皱眉:“指针是不是地址?”“数组和指针是不是一样的?”“为什么 * 有时候是解引用,有时候是乘法?”其实指针没那么神秘。只要把它拆开理解,就会发现它不过是一串数字,存的就...

C语言应用笔记:整数字节大小端翻转

在C语言中,实现大小端(Endian)翻转可以通过位操作或内存操作完成。以下提供两种常用方法:方法1:位运算(推荐)通过移位和掩码操作直接交换字节位置:// 16位翻转(安全版本) #define S...