c - 哈佛架构平台上的 NULL 指针问题

标签 c null harvard-architecture

本周我们在这里遇到了一个有趣的问题。

我们在哈佛架构嵌入式平台上使用 C 语言工作,该平台具有 16 位数据地址和 32 位代码地址。

当您使用函数指针时会出现此问题。如果你有像

这样的代码
if (fp) fp();

if (fp != 0) fp();

一切都很好。

但是如果你有这样的代码

if (fp != NULL) fp();

然后,因为 NULL 被定义为 (void *) 0,编译器(在本例中为 gcc)a) 不发出警告 b) 执行 16-与您的函数指针进行位比较,而不是 32 位比较。只要您的函数指针不恰好位于 64k 边界上就可以,因此所有底部 16 位都为 0。

目前我们有大量代码包含针对 NULL 的显式检查。其中大部分将是数据指针,但其中一些将是函数指针。 != NULL== NULL 的快速 grep 揭示了 3000 多个结果,许多人需要手动检查。

所以,我们现在想要的是

  1. 找到所有比较函数指针(但不是数据指针)的情况的方法(因此我们可以让它们与我们定义为 32 位 0 的 FP_NULL 进行比较),或

  2. 以正确的方式重新定义 NULL。

  3. (或者,我想, 更新我们的 gcc 端口以检测和 正确处理这种情况)。

我想不出任何适用于 1 的方法。对于 2,我能想到的唯一方法是将 NULL 重新定义为 0 函数指针,这对于绝大多数针对数据的比较来说是非常浪费的指针。 (32 位比较是 4 条指令,16 位比较是 1 条指令)。

有什么想法或建议吗?

最佳答案

在我看来,最简单的方法是将所有出现的 NULL 替换为 0。这适用于函数指针(如您所说)和对象指针。

这是 (2) 将 NULL 重新定义为普通 0 的变体。

但是您不能将函数指针与 NULL 进行比较这一事实是您实现中的一个错误。 C99 声明空指针常量的比较对于对象和函数指针都是可能的,并且 NULL 应该扩展到这个常量。

C-FAQ 问题的小补充 5.8 :

Q: Is NULL valid for pointers to functions?
A: Yes (but see question 4.13)

混合函数指针与(void *) 0

(对 R.. 评论的回复)。我相信一起使用函数指针和 (void *) 0 是明确定义的。在我的推理中,我将引用 C99 草案 1256 的部分内容,但不会引用大部分内容以保持其可读性。 C89应该也适用。

  • 6.3.2.3 (3) 定义整型常量表达式0 和这样一个转换为(void *) 的表达式作为空指针常量 .并且:“如果一个空指针常量被转换为一个 指针类型,生成的指针称为空指针,保证比较不相等 指向任何对象或函数的指针。”
  • 6.8.9 为指针操作数和空指针常量定义了==!= 操作数。对于这些:“如果一个操作数是指针而另一个是 空指针常量,空指针常量转换为指针的类型。”

结论:在fp == (void *) 0中,空指针常量被转换为fp的类型。此空指针可以与 fp 进行比较,如果它指向一个函数,则保证不等于 fp。 Assignment (=) 有一个类似的子句,所以 fp = (void *) 0; 也是定义良好的 C。

关于c - 哈佛架构平台上的 NULL 指针问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3889541/

相关文章:

c++ - _itoa 和 itoa 有什么区别?

cpu - 如何判断我的计算机是哈佛架构还是冯诺依曼架构?

architecture - 冯·诺依曼架构有何优点?

c - 如何使两个在其他方面相同的指针类型不兼容

c - JNI-未固定的原始数组错误

c - C 预处理器运算符 ##

c - 使用 pthread 读取文件并执行操作

java - 如何避免在方法链接中检查空值?

JavaScript - 未捕获的类型错误 : Cannot set property 'onclick' of null (Search Bar)

java - Java 中的 "this"引用是否为空