我有一个函数,使用省略号获取变量和以NULL结尾的指针参数列表。我知道可变长度模板参数列表。它与遗留代码有关。由于va_arg将终结符解释为Serializable *,以下两个调用是否会导致未定义的行为?这两个电话有什么区别?
void serialize(Serializable* first, ...) {
va_list vl;
va_start(vl, first);
while(1)
{
Serializable* arg = va_arg(vl, Serializable*);
if(arg == NULL)
break;
/* serialize arg here */
}
}
serialize(obj1, obj2, obj3, NULL);
serialize(obj1, obj2, obj3, nullptr);
答案 0 :(得分:2)
不,我不这么认为。
如果
ap
中的下一个参数的类型(升级后)与T
不兼容,则该行为是不确定的,除非:
- 一种类型是有符号整数类型,另一种类型是相应的无符号整数类型,并且值在两种类型中均可表示;或
- 一种类型是指向
void
的指针,另一种类型是指向字符类型(char
,signed char
或unsigned char
)的指针。
(这与C11的实际措辞非常匹配;请记住,va_arg
是由C而不是C ++定义的。)
现在,{11}总结了C11对“兼容类型”的定义,这告诉我们对于您的NULL
具有与Serializable*
兼容的类型,pointee类型是NULL
必须与Serializable
兼容。
现在another cppreference,所以您不知道它是什么,但是肯定不会与Serializable
兼容,除非它只是void
的类型别名或int
,您会很幸运。
使用nullptr
NULL
has an implementation-defined type,但再次参见上文。