为什么转换 vararg 函数参数很重要?

Why would casting a vararg function parameter matter?

提问人:Luchian Grigore 提问时间:3/22/2013 更新时间:3/22/2013 访问量:239

问:

最近,我遇到了一个问题,该函数接受可变数量的参数,并期望最后一个参数为空指针。我无权访问它的实现。

将最后一个参数转换为工作参数,但直接传入(不可用)不会:void*NULLnullptr

foo(x,y,(void*)NULL);   //okay
foo(x,y,NULL);          //crash

IMO 这不应该有什么不同,但话又说回来,我以前错了。你能想出任何理由让演员们有所作为吗?或者这只是一个意外(一些不同步或错误的构建或沿着这些路线的 smth)

很抱歉,我无法提供更多详细信息。

C++ 转换 可变函数

评论

3赞 Pubby 3/22/2013
因为是整数,是指针?varargs 不会像普通函数那样转换任何内容。NULL(void*)NULL
0赞 Luchian Grigore 3/22/2013
@Pubby我只是看不出这在函数内部有什么关系。你能举个例子吗?
0赞 Mircea Ispas 3/22/2013
我认为这就是问题所在,请改用 nullptr,它应该可以工作
0赞 Alok Save 3/22/2013
“期望最后一个是空指针”,接口文档是否对此参数有任何说明?
0赞 Luchian Grigore 3/22/2013
@Felics它适用于演员阵容,我想知道为什么

答:

12赞 Oliver Charlesworth 3/22/2013 #1

嗯,是 C++ 中的一个整数常量,而绝对是一个指针类型。NULL(void *)NULL

因此,可以想象,当它们插入到 var-arg 列表中时,它们可能会有不同的大小。因此,如果后面有另一个参数,这肯定会有所作为。如果没有,你最终可能会从 var-arg 函数内部读取半垃圾。

1赞 ecatmur 3/22/2013 #2

NULL是 null 指针常量,因此必须是“计算结果为零的整数类型的整数表达式 prvalue 或 std::nullptr_t 类型的 prvalue”。如果不可用,我们可以假设它是一个零值整数常量 prvalue,例如 .失败表明参数和(提升)类型的 varargs 调用语义不同,例如,如果指针是 64 位和 32 位。nullptr0void *NULLint

2赞 Michael Kohne 3/22/2013 #3

当您使用可变数量的参数(可变参数函数)时,堆栈的构建方式将遵循基于类型的堆栈构建规则。但是被调用的函数并不能肯定地知道堆栈上到底有什么。它只需要做出假设并继续前进。这就是为什么将错误的参数传递给 printf 如此危险的原因——如果你告诉它期待一个长 int,而你只给它一个短 int,它会从堆栈中读取比你输入的数据更多的数据,并且会发生不好的事情。

对于您的问题,整数在您的体系结构上可能不是指针大小。(也就是说,sizeof(int) != sizeof(void*))。由于 NULL 作为整数被推送到堆栈上,如果它没有指针大小,那么当函数从堆栈中拉出“指针”时,它会抓取谁知道什么。

整数可能最终出现在寄存器中,而指针最终出现在堆栈上,或者可能位于不同的寄存器文件中。我从未在可变参数函数中看到过这一点,但我怀疑至少有一些编译器和架构可以做到这一点。在这种情况下,被调用的函数在错误的位置查找数据,同样,它没有任何好处。