在可变函数中提升整数
Promotion of integer in variadic functions
为什么下面代码中的第一个 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;
}
我能理解为什么第二个 f()
调用修复有效。但是我不明白为什么第一个 f()
调用会导致这个问题。你能解释一下这种行为吗?
在第一次调用中,参数作为 int
传递。除非 int
是使用 64 位表示的,否则您可以通过尝试从中提取 int64_t
来调用未定义的行为。根据您程序的输出判断 int
未在您的平台上使用 64 位呈现。
来自第 7.16.1.1/2 节 C11 标准(强调我的):
The va_arg
macro expands to an expression that has the specified type and the value of the next argument in the call. The parameter ap
shall have been initialized by the va_start
or va_copy
macro (without an intervening invocation of the va_end
). Each invocation of the va_arg
macro modifies ap
so that the values of successive arguments are returned in turn. The parameter type shall be a type name specified such that the type of a pointer to an object that has the specified type can be obtained simply by postfixing a * to type. If there is no actual next argument, or if type is not compatible with the type of the actual next argument (as promoted according
to the default argument promotions), the behavior is undefined, except for the following cases:
— one type is a signed integer type, the other type is the corresponding unsigned integer type, and the value is representable in both types;
— one type is pointer to void and the other is a pointer to a character type.
为什么下面代码中的第一个 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;
}
我能理解为什么第二个 f()
调用修复有效。但是我不明白为什么第一个 f()
调用会导致这个问题。你能解释一下这种行为吗?
在第一次调用中,参数作为 int
传递。除非 int
是使用 64 位表示的,否则您可以通过尝试从中提取 int64_t
来调用未定义的行为。根据您程序的输出判断 int
未在您的平台上使用 64 位呈现。
来自第 7.16.1.1/2 节 C11 标准(强调我的):
The
va_arg
macro expands to an expression that has the specified type and the value of the next argument in the call. The parameterap
shall have been initialized by theva_start
orva_copy
macro (without an intervening invocation of theva_end
). Each invocation of theva_arg
macro modifiesap
so that the values of successive arguments are returned in turn. The parameter type shall be a type name specified such that the type of a pointer to an object that has the specified type can be obtained simply by postfixing a * to type. If there is no actual next argument, or if type is not compatible with the type of the actual next argument (as promoted according to the default argument promotions), the behavior is undefined, except for the following cases:— one type is a signed integer type, the other type is the corresponding unsigned integer type, and the value is representable in both types;
— one type is pointer to void and the other is a pointer to a character type.