在可变函数中提升整数

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.