【发布时间】:2011-04-22 19:37:47
【问题描述】:
这周我们在这里遇到了一个有趣的问题。
我们正在哈佛架构嵌入式平台上使用 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 个结果,许多人需要手动检查。
所以,我们现在想要的是要么
一种查找所有比较函数指针(但不是数据指针)的情况的方法(因此我们可以将它们与定义为 32 位 0 的 FP_NULL 进行比较),或者
重新定义 NULL 以使其做正确的事情。
(或者,我想, 更新我们的 gcc 端口以检测和 正确处理这种情况)。
我想不出任何适用于 1 的方法。我能想到的唯一方法 2 是将 NULL 重新定义为 0 函数指针,这对于绝大多数针对数据的比较来说是非常浪费的指针。 (32 位比较是 4 条指令,16 位比较是 1 条指令)。
有什么想法或建议吗?
【问题讨论】:
-
只是为了记录,
gcc的哪个版本对你这样做? -
它是 gcc 3.3.3,但它是我们自己的平台端口。
-
这肯定是实现中的一个错误。
(void *) 0被 C 官方认可为 空指针常量,这意味着它必须在函数指针上下文(包括比较)中转换为正确的空指针值。换句话说,(void *) 0不是数据指针,即使它似乎包含对数据指针类型的强制转换,它仍然是那个“灵活的”空指针常量。编译器似乎假定(void *) 0严格来说是一个数据指针,这是不正确的。
标签: c null harvard-architecture