可变参数C函数中的空值:是否需将0强制转换为char*?
可变参数函数中传递空指针是否需要强制转换?
首先直接给结论:是的,在绝大多数常见系统和标准编译器环境下,你必须使用(char*)0这种强制转换,否则你的代码会触发未定义行为,可能在某些平台上运行异常。
接下来拆解背后的原因:
- 可变参数函数的
va_arg宏完全依赖你指定的类型来从参数列表中取值。你这里要取的是char*类型的参数,但直接传0的话,这个0的原生类型是int,并非指针类型。 - 在不同系统架构中,
int和指针的大小可能不匹配:- 32位系统里,
int和指针都是4字节,可能碰巧能正常工作,但这只是巧合,绝非标准规定的可靠行为。 - 64位系统里,
int通常是4字节,而指针是8字节。这时候直接传0(int类型),va_arg尝试读取8字节的char*值时,会把0后面的4字节栈垃圾数据一起读进来,形成一个无效的非空指针,导致循环无法终止,甚至引发程序崩溃。
- 32位系统里,
那为什么你在Linux x64下运行原代码能得到正确输出?
这是因为x64的System V调用约定中,整数和指针参数都是通过寄存器传递的。0作为int被放进寄存器后,va_arg读取char*时直接从同一个寄存器取数,而x64架构中空指针的表示刚好是全0,所以碰巧生效了。但这是依赖特定调用约定的未定义行为,绝对不能当成通用写法。
最后,符合C标准且可移植的写法应该是:
return f("a","b",(char*)0);
这样编译器会明确把终止值当成char*类型的空指针传递,va_arg能正确读取到预期的空指针,循环会在正确的时机终止。
内容的提问来源于stack exchange,提问作者effbiae
相关产品推荐
相关产品推荐

