省略号NULL,nullptr和未定义的行为

时间:2019-02-04 11:35:59

标签: c++ null variadic-functions nullptr

我有一个函数,使用省略号获取变量和以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);

1 个答案:

答案 0 :(得分:2)

不,我不这么认为。

引用cppreference.com on va_arg

  

如果ap中的下一个参数的类型(升级后)与T不兼容,则该行为是不确定的,除非:

     
      
  • 一种类型是有符号整数类型,另一种类型是相应的无符号整数类型,并且值在两种类型中均可表示;或
  •   
  • 一种类型是指向void的指针,另一种类型是指向字符类型(charsigned charunsigned 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,但再次参见上文。