【发布时间】:2017-02-19 08:47:12
【问题描述】:
我想编写一个通用函数来检测指向某个任意类型的指针数组是否包含NULL。我最初的尝试是这样的:
bool find_null (void *ptrs, size_t num_ptrs) {
void **array = ptrs;
size_t i;
for (i = 0; i < num_ptrs; ++i) {
if (array[i] == NULL) return true;
}
return false;
}
有人指出,这可能会导致严格的别名违规,因为指向 Foo 的指针数组将作为指向 void 的指针数组进行访问,这未列为对象的允许访问方式之一允许在 C.2011 §6.5¶7 中访问。
我可以改写函数以将指针数组访问为unsigned char *,但我不确定如何在不破坏严格别名的情况下执行NULL 检查。有人可以提供有效的技术吗?
bool find_null (void *ptrs, size_t num_ptrs) {
unsigned char *array = ptrs;
void *p;
size_t i;
for (i = 0; i < num_ptrs; ++i) {
memcpy(&p, array + i * sizeof(p), sizeof(p));
if (p == NULL) return true;
/*
* Above seems to still break strict aliasing.
* What should be done instead?
*/
}
return false;
}
我们的目标是编写一个与特定类型函数一样工作的通用函数。换句话说,以下函数的通用版本:
bool find_null_Foo (Foo *array[], size_t num_ptrs) {
size_t i;
for (i = 0; i < num_ptrs; ++i) {
if (array[i] == NULL) return true;
}
return false;
}
【问题讨论】:
-
这通常是不可能的。不要求
sizeof(void*)等于sizeof(Foo*)。它们在不可字节寻址的机器上可能是不相等的,其中sizeof(void*)比sizeof(Foo*)稍大一点,因为需要记录指针所引用的字中的字节。 -
您希望代码只考虑值为
(void*)NULL的空指针,还是要处理平台具有各种空指针值的可能性? (当然,所有空指针都彼此等同——尽管它们可能有不同的编码。) -
@RaymondChen:感谢您提出这个问题,这是一个有效的观点。我发布了一个答案,应该解释这一点。但是,对于这样的机器,我可能最终会将其设计为 30 位可寻址(对于 4 字节字)或 61 位可寻址(对于 8 字节字),而不是尝试处理不同大小的指针。
-
@jxh 祝 PDP-10 好运。 36 位字可寻址地址空间和 36 位寄存器。
-
@RaymondChen:在这种情况下是 34 位可寻址的。
标签: c pointers language-lawyer void strict-aliasing