为什么转换变量函数参数很重要?
Why would casting a vararg function parameter matter?
最近我遇到了一个函数的问题,它接受可变数量的参数,并期望最后一个是空指针。我无法访问它的实现
将最后一个参数转换为void*
有效,但直接传递NULL
(nullptr
不可用)则不能:
foo(x,y,(void*)NULL); //okay
foo(x,y,NULL); //crash
在我看来,这不应该有什么区别,但话说回来,我以前就错了。你能想到演员阵容有什么不同的原因吗?或者这只是一个意外(某种设计或错误的构建或史密斯)。沿着这些行)
很抱歉,我不能提供更多的细节。
在c++中,NULL
是一个整型常量,而(void *)NULL
则是一个指针类型。
因此,当插入var-arg列表时,它们可能具有不同的大小。如果后面有另一个参数,这肯定会有区别。如果没有,您可能会从var-arg函数内部读取一半的垃圾。
当您使用可变数量的参数(可变函数)时,构建堆栈的方式遵循构建堆栈的基于类型的规则。但是被调用的函数并不知道,栈上到底有什么。它只需要做出假设,然后继续。这就是为什么给printf传递错误的参数是如此危险——如果你告诉它期待一个长int,而你只给它一个短int,它将从堆栈中读取比你放入的更多的数据,并且会发生不好的事情。
对于你的问题,整数在你的体系结构上可能不是指针大小的。(也就是说sizeof(int) != sizeof(void*))。因为NULL是作为一个整数被推送到堆栈上的,如果它不是指针大小的,那么当函数从堆栈中取出一个"指针"时,它会抓取谁知道是什么。
整数可能在寄存器中结束,而指针可能在堆栈中结束,或者可能在不同的寄存器文件中结束。我从未在可变函数中见过这种情况,但我怀疑至少有一些编译器&架构可以做到这一点。在这种情况下,被调用的函数在错误的位置查找数据,同样,没有任何好的结果。
NULL
是一个空指针常量,所以必须是"一个整型常量表达式prvalue,计算结果为0或std::nullptr_t
类型的prvalue ."如果nullptr
不可用,我们可以假设它是一个零值的整型常量prvalue,例如0
。失败表明void *
参数的变量调用语义与NULL
(提升)类型的变量调用语义不同,例如,如果指针是64位而int
是32位。
- lambda参数转换为constexpr技巧,然后获取带链接的数组
- 如何将向量中的可变参数转换为参数的持有者?
- c++ 构造函数 将 1 个字符串参数转换为 3 个属性
- 将空*参数转换为各种类型的参数是UB吗?
- 将可变参数模板参数转换为 JSON 字符串
- C++ 如何将函数参数转换为字符串
- 功能指针参数参数转换为const
- 避免对模板运算符过载的隐式参数转换
- 将C 方法参数转换为模板参数会因编译错误而失败
- 将参数转换为lpwstr createProcess
- 在与时间一起使用 srand 时,如果我没有time_t参数明确地将参数转换为无符号的 int 参数,这有关系吗?
- 将C++整型模板参数转换为整型"longer"型
- 将参数转换为目标类型时,复制用于直接初始化的构造函数省略
- 将命令行参数转换为qimage
- 将可变数量的参数转换为明确的数量
- SDL 方法,参数转换
- 通过错误检查将参数转换为整数
- 功能参数转换为儿童类C
- 参数转换在课堂上
- 在窗口上将格式化的 C 字符串和参数转换为 wstring