写 C 程序时,很多与“大小、地址、偏移”有关的问题,表面上看只是几个整数运算,真正落到跨平台环境里却很容易踩坑。 提供的类型和宏,正是为这些基础但关键的场景准备的。下面按照“对象大小”“指针差值”“空指针判断”“结构体偏移”几个常见问题展开,帮助你判断什么时候该用它,以及为什么它比直接写 int 或手算地址更稳妥。
为什么要了解
是 C 标准库中的基础头文件,主要用于提供与内存、地址和偏移相关的通用定义。在编写需要兼顾不同编译器、不同平台位宽的代码时,它的价值尤其明显。
这个头文件里最常见的内容,可以分成两类:
- 类型:例如
size_t、ptrdiff_t - 宏:例如
NULL、offsetof
它们看起来都很基础,但恰恰是这类基础定义,决定了代码在处理数组长度、结构体布局和指针运算时是否足够可靠。
处理大小和指针差值时该用什么类型
size_t:表示对象大小和数组长度
size_t 是无符号整数类型,最常见的用途是表示对象大小、内存块长度以及数组元素个数。它通常和 sizeof 配合使用,因为 sizeof 的结果类型本身就是 size_t。
相比直接使用 int,size_t 的优势在于它能随着平台能力变化,正确表示更大的对象或更长的数组长度,因此更适合写可移植代码。
size_t num_elements = sizeof(array) / sizeof(array[0]);
这类写法在统计数组元素数量时非常常见,也比手写常量更安全。
ptrdiff_t:表示两个指针之间的距离
ptrdiff_t 是有符号整数类型,用来保存两个指针相减后的结果。因为两个指针之间的差值可能为负,所以它必须是有符号类型。
如果你需要比较两个元素位置、计算前后偏移,或者处理遍历区间中的距离,ptrdiff_t 比普通整数类型更符合语义,也更接近标准库的设计预期。
ptrdiff_t index_diff = &a - &b;
这里得到的是两个指针之间相差多少个元素,而不是相差多少字节。
两个最常用的宏怎么理解
NULL:明确表示空指针
NULL 是空指针常量,用来表示指针当前不指向任何有效对象。虽然某些场景里直接写 0 也能工作,但在指针语义上使用 NULL 更清晰,可读性也更好。
int *p = NULL;
if (p == NULL) {
// p 是一个空指针
}
这类写法常用于初始化指针、函数返回失败状态,或者在释放资源后显式清空指针。
offsetof:获取结构体成员的字节偏移
offsetof 宏用于计算某个结构体成员,相对于结构体起始地址的偏移量,单位是字节。只要你需要关注内存布局,例如序列化、底层协议、二进制解析或与硬件数据结构对接,它都会非常实用。
struct Student {
char name[50];
int age;
};
size_t offset_of_age = offsetof(struct Student, age);
上面这段代码得到的是 age 成员在 Student 结构体中的起始偏移,而不是它的值,也不是结构体总大小。
示例:用 查看结构体大小和成员偏移
下面这段示例代码展示了 的典型用法:既查看结构体整体大小,也查看成员在结构体中的位置。

// www.ja vascriptcn.com code example
#include
#include
struct Point {
int x;
int y;
};
int main() {
size_t point_size = sizeof(struct Point);
printf("Size of Point: %zu bytesn", point_size);
size_t x_offset = offsetof(struct Point, x);
printf("Offset of x: %zu bytesn", x_offset);
size_t y_offset = offsetof(struct Point, y);
printf("Offset of y: %zu bytesn", y_offset);
return 0;
}
从执行逻辑看,这段程序做了三件事:
- 用
sizeof(struct Point)取得整个结构体占用的字节数 - 用
offsetof(struct Point, x)计算x的偏移 - 用
offsetof(struct Point, y)计算y的偏移
这类输出很适合用来验证结构体布局,尤其是在你怀疑对齐规则会影响结果时。
实际编写 C 代码时怎么选
如果只是记概念, 看起来并不复杂;真正重要的是,遇到具体问题时能否选对类型和宏。

- 需要表示对象大小、数组长度:优先用
size_t - 需要保存两个指针相减的结果:用
ptrdiff_t - 需要表达“当前不指向任何对象”:用
NULL - 需要计算结构体成员相对起点的字节位置:用
offsetof
这些定义共同解决的核心问题,就是让代码在“内存相关操作”上更符合标准,也更适合跨平台维护。







