You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

关于C语言中空指针常量与空指针的关系及相关标准疑问的技术问询

关于C语言中空指针常量与空指针的关系及相关标准疑问的技术问询

咱们先从C17标准草案的定义入手,直接看原文:

来自C17草案(6.3.2.3 ¶3):
一个值为0的整数常量表达式,或者被转换为void *类型的此类表达式,被称为空指针常量。67)如果一个空指针常量被转换为指针类型,得到的指针被称为空指针,它保证与任何指向对象或函数的指针比较不相等。

67)宏NULL在<stddef.h>(以及其他头文件)中被定义为空指针常量[...]。

从这个定义出发,我们可以明确这些空指针常量:

  • 0
  • 0UL
  • (void *)0
  • (void *)0UL
  • NULL

而下面这些则是空指针:

  • (int *)0
  • (int *)0UL
  • (int *)(void *)0
  • (int *)(void *)0UL
  • (int *)NULL

有意思的是,这些空指针都不属于“空指针常量”的范畴——它们是常量表达式转换后的指针类型值,而非原始的空指针常量本身。

这里还要注意一个特殊情况:(void *)0和(void *)0UL既是空指针常量,也是空指针。因为void *本身是一种指针类型,咱们再看C17草案的补充说明(6.2.5 ¶19-20):

void类型包含空值集合;它是一种无法完成的不完整对象类型。
[...]
指针类型可以从函数类型或对象类型(被称为引用类型)派生而来。[...]指针类型是一种完整的对象类型。

简单总结:void不是指针类型,它是不完整类型;但void *是标准定义的指针类型,所以当空指针常量被转换为void *时,它同时具备了空指针常量和空指针的属性。

那反过来,0、0UL、NULL这些空指针常量,它们本身不是空指针——因为它们没有被转换为指针类型(严格来说,标准只要求NULL被定义为“空指针常量”,允许它同时也是空指针,但并没有强制要求必须这么定义)。

现在回到大家最关心的核心问题:

  1. 是不是每个空指针常量都是空指针?(NULL真的不是空指针吗?)
    答案是否定的。只有当空指针常量被转换为指针类型时,它才成为空指针。像0这种整数形式的空指针常量,本身是整数类型,不是指针;而NULL如果被定义为0或者0UL,那它也只是整数常量,不是指针——只有当它被转换为指针类型后,才变成空指针。

  2. 如果某些空指针常量不是空指针,那它们算不算一种“非空指针”?
    这里其实是个语言上的“括号悖论”:我们可以把“non-null pointer”理解成「[非空]指针」(即不是空指针的指针),或者「非[空指针]」(即不是空指针的任何值)。如果是前者,那这些非指针类型的空指针常量根本不属于“指针”范畴,自然谈不上是“非空指针”;如果是后者,那它们确实不是空指针,但这么表述容易造成混淆,标准里的“non-null pointer”应该特指前者——即指向有效对象/函数的指针,而非空指针的指针类型值。

备注:内容来源于stack exchange,提问作者Lover of Structure

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.22 12:09:38