我们有很多遗留的C ++代码,其函数带有可变数量的指针参数。在每种情况下,空指针都表示参数列表的结尾。在遗留代码中,文字0用于空指针。因为C ++变量参数列表函数没有对变量参数的类型进行原型化,所以终止参数作为整数0传递。在某些64位环境中,整数是32位而指针是64位。是否存在被调用函数将看到非零指针的风险(即,低位32位字为零,但高位32位包含垃圾)?将所有0个参数更改为nullptr可能是正确的方法。我的问题是:这有必要吗?即如果我们不这样做,是否存在真正的错误风险?
class mytype;
void foo(mytype*, ...);
mytype a, b, c;
foo(&a, &b, &c, 0); //is this ok ?
foo(&a, &b, &c, nullptr); //or must it be so ?
答案 0 :(得分:3)
您已经对您的用户进行了教育。如果将每个参数解压缩为va_arg(ap, mytype*)
,则用户应使用(mytype*)(0)
而不是0
向列表末尾发出信号。您现有的代码始终具有未定义的行为。即使nullptr
也不合适,因为当它是无类型参数时,它将作为void*
传递,因此正确的参数再次为static_cast<mytype*>(nullptr)
。
如果您要求针对未定义的行为进行特定于平台的制裁,请咨询您的供应商。
答案 1 :(得分:0)
(部分)解决方案是使用运算符重载:
void saferfoo(mytype* a0, mytype* a1, ..., mytype* an, int zero) {
foo(a0, a1, ..., an, static_cast<mytype*>(nullptr));
}
这里...
不是来自C ++语言的省略号,而是我们人类语言的省略号。
您必须为代码中存在的每个参数定义函数,您还必须重新编译相关代码。由于只有过去/现在误用foo
受影响,你可以这样做并使用棒球棒来处理未来foo
的误用。
答案 2 :(得分:-3)
在我看来,使用0是一种非便携式解决方案。根据编译器的不同,它可以转换为数组元素的数据类型,也可以转换为int(0)。
因此,我个人建议在这种情况下始终使用NULL。