位置:首页 > C > C 语言 :size_t、ptrdiff_t、NULL 和 offsetof 一次看懂

C 语言 :size_t、ptrdiff_t、NULL 和 offsetof 一次看懂

时间:2026-08-22  |  作者:骑光打字机  |  阅读:0

目录

  1. 为什么要了解
  2. 处理大小和指针差值时该用什么类型
  3. 两个最常用的宏怎么理解
  4. 示例:用 查看结构体大小和成员偏移
  5. 实际编写 C 代码时怎么选

前言

写 C 代码时,涉及对象大小、指针差值和结构体成员位置的问题,看似只是几个基础语法点,实际却直接影响代码的可移植性和可维护性。本文把 里最常用的类型与宏拆开讲清楚,再结合一个结构体示例说明它们各自解决什么问题,读完你就能判断哪些场景该用 size_t、哪些场景该交给 offsetof

写 C 程序时,很多与“大小、地址、偏移”有关的问题,表面上看只是几个整数运算,真正落到跨平台环境里却很容易踩坑。 提供的类型和宏,正是为这些基础但关键的场景准备的。下面按照“对象大小”“指针差值”“空指针判断”“结构体偏移”几个常见问题展开,帮助你判断什么时候该用它,以及为什么它比直接写 int 或手算地址更稳妥。

为什么要了解

是 C 标准库中的基础头文件,主要用于提供与内存、地址和偏移相关的通用定义。在编写需要兼顾不同编译器、不同平台位宽的代码时,它的价值尤其明显。

这个头文件里最常见的内容,可以分成两类:

  • 类型:例如 size_tptrdiff_t
  • 宏:例如 NULLoffsetof

它们看起来都很基础,但恰恰是这类基础定义,决定了代码在处理数组长度、结构体布局和指针运算时是否足够可靠。

处理大小和指针差值时该用什么类型

size_t:表示对象大小和数组长度

size_t 是无符号整数类型,最常见的用途是表示对象大小、内存块长度以及数组元素个数。它通常和 sizeof 配合使用,因为 sizeof 的结果类型本身就是 size_t

相比直接使用 intsize_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 结构体中的起始偏移,而不是它的值,也不是结构体总大小。

示例:用 查看结构体大小和成员偏移

下面这段示例代码展示了 的典型用法:既查看结构体整体大小,也查看成员在结构体中的位置。

展示结构体 Point 的大小与成员偏移关系的信息图,说明 sizeof 和 offsetof 在同一示例中的作用。
结构体大小与成员偏移示意同一段结构体代码里,sizeof 负责回答“整体多大”,offsetof 负责回答“成员在哪”。
// 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 代码时怎么选

如果只是记概念, 看起来并不复杂;真正重要的是,遇到具体问题时能否选对类型和宏。

展示 <stddef.h></a> 中 size_t、ptrdiff_t、NULL 与 offsetof 各自解决的问题和对应使用场景的信息图。
常用定义速查图 里最常见的类型和宏放到具体问题里看,更容易判断什么时候该用哪一个。
  • 需要表示对象大小、数组长度:优先用 size_t
  • 需要保存两个指针相减的结果:用 ptrdiff_t
  • 需要表达“当前不指向任何对象”:用 NULL
  • 需要计算结构体成员相对起点的字节位置:用 offsetof

这些定义共同解决的核心问题,就是让代码在“内存相关操作”上更符合标准,也更适合跨平台维护。

免责声明:文中图文均来自网络,如有侵权请联系删除,心愿游戏发布此文仅为传递信息,不代表心愿游戏认同其观点或证实其描述。

相关文章

更多

精选合集

更多

大家都在玩

热门话题

大家都在看

更多