Lon*_*ner 0 c signed variadic-functions integer-promotion unsigned-integer
为什么f()下面的代码中的第一个调用最终会打印出-2我传递给它的代码4294967294呢?
#include <stdio.h>
#include <stdint.h>
#include <stdarg.h>
#include <stdlib.h>
void f(int64_t i, ...)
{
va_list ap;
int64_t j;
va_start(ap, i);
j = va_arg(ap, int64_t);
printf("%jd %jd\n", (intmax_t) i, (intmax_t) j);
va_end(ap);
}
int main()
{
f(-1, -2); // Prints -1 4294967294 (bug!)
f(-1, (int64_t) -2); // Prints -1 -2 (fix!)
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我能理解为什么f()修复的第二次调用有效.但我无法理解为什么第一个f()电话会导致这个问题.你能解释一下这种行为吗?
在第一次调用中,参数作为一个传递int.除非int使用64位表示,否则通过尝试从中提取a int64_t来调用未定义的行为.int在您的平台上使用64位不会显示程序输出.
从第7.16.1.1/2节 C11标准(强调我的):
的
va_arg宏扩展为具有指定的类型和在呼叫中的下一个参数的值的表达式.该参数ap应由va_start或va_copy宏初始化(无需干预调用va_end).每次调用va_arg宏都会修改,ap以便依次返回连续参数的值.参数类型应该是指定的类型名称,以便可以通过将*固定为类型来获得指向具有指定类型的对象的指针的类型.如果没有实际的下一个参数,或者type与实际的下一个参数的类型不兼容(根据默认参数提升而提升),则行为是未定义的,除了以下情况:- 一种类型是有符号整数类型,另一种类型是相应的无符号整数类型,并且该值可在两种类型中表示;
- 一种类型是指向void的指针,另一种是指向字符类型的指针.