可变函数中的std :: nullptr_t参数

时间:2014-04-29 19:36:37

标签: c++ c++11

显然,当没有参数(通过std::nullptr_t)传递时,void *参数被转换为类型为...的空指针(N3337的第5.2.2 / 7节)。这意味着要正确传递空char *指针,例如,仍需要强制转换:

  

some_variadic_function(“a”,“b”,“c”,(const char *)std :: nullptr);

因为无法保证null void *具有与null char *相同的位模式。正确的吗?

这也意味着std::nullptr在这种情况下0没有优势,除非为了清晰起见。

2 个答案:

答案 0 :(得分:7)

你问:

  

因为无法保证null void *具有与null char *相同的位模式。正确的吗?

嗯,实际上,这种保证确实存在,Deduplicator的答案已经显示了标准要求的地方。但这与你的问题无关。

void *传递给可变参数函数,并使用va_arg作为char *访问它,特别允许作为特殊例外。

C ++ 11:

  

18.10其他运行时支持[support.runtime]

     

1个标题<csetjmp>(非本地跳转),<csignal>(信号处理),<cstdalign>(对齐),<cstdarg>(可变参数),<cstdbool>__bool_true_false_are_defined)。 (运行环境   getenv()system())和<ctime>(系统时钟clock()time())提供了与C代码的进一步兼容性。

     

2这些标头的内容与标准C库标题<setjmp.h><signal.h><stdalign.h><stdarg.h><stdbool.h>,{{ 1}}和<stdlib.h>分别具有以下内容   变化:

     

[......没有关于<time.h>]

C99:

  

7.15.1.1 va_arg

     

[...]如果没有实际的下一个参数,或者 type 与实际的下一个参数的类型不兼容(根据默认参数促销提升),行为未定义,除以下情况外:

     

- 一种类型是有符号整数类型,另一种类型是相应的无符号整数类型,并且该值可在两种类型中表示;

     

- 一种类型是指向void的指针,另一种是指向字符类型的指针。

但是,这确实意味着在va_argT1两种类型具有相同的表示和对齐要求的其他情况下,如果将T2传递给可变参数函数,则行为未定义,它被检索为T1

这样做的一个示例:允许传递T2并以(void *) 0方式访问它,传递char *并允许(void *) 0访问它,但是传递{{} 1}}并以unsigned char *访问它是允许。如果编译器能够内联对可变参数函数的调用,并根据标准的严格要求进行优化,那么这种不匹配可能会严重破坏。

  

这也意味着(char *) 0在这种情况下unsigned char *没有优势,除非为了清晰起见。

我肯定使用std::nullptr而不进行投射,即使在这一特殊情况下它是有效的。很难看出它是有效的。如果无论如何都包含一个强制转换,0就像空指针值一样清晰。

答案 1 :(得分:2)

你错了。少数保证之一是char*具有与相应void*相同的大小和表示。

  

3.9.2复合类型§4

     

指向cv-qualified(3.9.3)或cv-unqualified void的指针可用于指向未知类型的对象。   这样的指针应该能够保存任何对象指针。 cv void*类型的对象应具有相同的对象   表示和对齐要求为cv char*

编辑:看起来this answer by hvd更好,显示了一些特定于问题的可变函数部分的陷阱。