NULL 数据指针是否与 NULL 函数指针相同?

Is NULL data-pointer the same as NULL function-pointer?

POSIX 要求(我认为)函数指针可以存储在传递给期望 void* 参数的函数的 void* and/or 类型的变量中,即使这严格来说是非标准的.

我的问题是:如果我测试这样一个 variable/argument 的 NULL-ness,if (!(variable or argument)) 说,结果是 true,这是否一定意味着函数指针NULL? NULL void* data-pointer 的位模式是否可以等同于非 NULL function-pointer 值?任何理智的实施都会这样做吗?是否有任何常见的实现可以做到这一点?

编辑:this answer(诚然是另一个问题)让我想知道在测试 NULL 性之前是否必须将 void* 中间值转换回原始函数指针类型,否则就是 UB。 .. 真的吗?发表回答的人可以权衡一下这个问题吗?

这个 C11 Draft Standard 建议,虽然不是 核心 标准的一部分,但将函数指针转换为对象指针(出于测试目的,如您的 NULL-check) 属于“通用扩展名”类别(附件 J.5):

J.5.7 Function pointer casts

1     A pointer to an object or to void may be cast to a pointer to a function, allowing data to be invoked as a function (6.5.4).

2     A pointer to a function may be cast to a pointer to an object or to void, allowing a function to be inspected or modified (for example, by a debugger) (6.5.4)

C 2018 6.3.2.3 4 说:

Conversion of a null pointer to another pointer type yields a null pointer of that type. Any two null pointers shall compare equal.

与第7段不同,本段不限制转换为指向对象类型的指针或指向函数类型的指针。因此,如果将某个函数指针类型的空指针转换为 void *,结果是一个空指针,然后将 ! 应用于它会产生 1.

相反,如果将 ! 应用于指针产生 1,则它必然来自空指针,这更加困难。我们可以想象一些非空函数指针,当转换为 void * 时,会产生一个空指针。考虑到 POSIX 允许函数指针临时存储在 void * 中的意图,我们可以得出结论,将指向函数的指针转换为 void * 永远不会导致空指针。

Could the bit pattern for a NULL void* data-pointer ever equate to a non-NULL function-pointer value?

C 标准不讨论用于表示指针的位模式。语义是根据值建立的。

Would any sane implementation do this?

当然,某些硬件上的裸机引导代码可能会将可执行指令放在地址零处,并出于某种原因在那里调用函数,也可能使用地址零作为空指针。它将简单地设计为不依赖于地址为零的函数未被测试为空指针。

在这种特殊情况之外,即出于所有实际目的,不这样做。如果某些软件决定它需要空指针的特殊表示,它会为此留出一些地址,而不将该地址用于任何普通函数或对象。

如果一个实现是针对一个平台,其中空代码指针的通用惯用位模式与空数据指针的通用惯用位模式不同,它可以自由地暴露指针的事实与程序员不同,或者将指针操作包装在一个抽象中,使它们的行为相同。该标准的作者并没有试图猜测哪种方法更有用,因为实际为相关平台编写代码的人比委员会更有资格判断每种方法的优缺点。

在目标平台对两种空指针使用相同表示的更为常见的情况下,标准的作者会期望实现以这种方式存储两种指针,但也会认为这样的实现应该以这种方式表现的想法足够明显,以至于没有必要花费笔墨来推荐这种行为。

标准未能强制执行常见行为并不意味着任何关于实现应该做任何其他事情的判断,而只是承认实现可能存在于某些其他行为有时可能比普通行为更有用的地方。