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

std::nullptr_t arguments in variadic functions

本文关键字:参数 函数 变参 nullptr std      更新时间:2023-10-16

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

some_variadic_function("a", "b", "c", (const char *( std::nullptr(;

因为不能保证空void *与空char *具有相同的位模式。正确?

这也意味着在这种情况下,除了可能为了清楚起见之外,std::nullptr0没有任何优势。

你问:

因为不能保证空void *与空char *具有相同的位模式。正确?

好吧,实际上,这种保证确实存在,重复数据删除器的答案已经显示了标准要求这一点的地方。但这与您的问题无关。

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

C++11:

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

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><stdlib.h><time.h> 相同,如下所示 变化:

[...没有关于va_arg]

C99:

7.15.1.1 va_arg

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

-- 一种类型是有符号整数类型,

另一种类型是对应的无符号整数类型,该值在两种类型中都是可表示的;

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

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

例如:允许传递(void *) 0并按char *访问它,也允许传递(void *) 0并按unsigned char *访问它,但不允许传递(char *) 0并按unsigned char *访问它。如果编译器能够内联对可变参数函数的调用,并根据标准的严格要求进行优化,则此类不匹配可能会严重中断。

这也意味着,在这种情况下,除了可能为了清楚起见之外,std::nullptr0没有任何优势。

我绝对不会在不强制转换的情况下使用nullptr,即使在这种特殊情况下它是有效的。很难看出它是有效的。如果无论如何都包含强制转换,则(char *) 0与空指针值一样清晰。

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

3.9.2 化合物类型 §4

指向符合 cv 条件 (3.9.3( 或不符合 cv 条件的 void 的指针可用于指向未知类型的对象。 这样的指针应该能够容纳任何对象指针。cv void* 类型的对象应具有相同的 作为简历char*的表示和对齐要求。

编辑:看起来hvd的这个答案更好,显示了更多特定于问题的可变参数函数部分的陷阱。