在可变函数中提升整数

时间:2016-10-20 05:34:00

标签: c variadic-functions signed unsigned-integer integer-promotion

为什么下面代码中的第一个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()调用会导致此问题。你能解释一下这种行为吗?

1 个答案:

答案 0 :(得分:5)

在第一次调用中,参数将作为int传递。除非使用64位表示int,否则通过尝试从中提取int64_t来调用未定义的行为。根据您的程序int的输出判断,不会使用平台上的64位来显示。

来自第7.16.1.1/2节 C11标准(强调我的):

  

va_arg宏扩展为具有指定类型和调用中下一个参数值的表达式。参数ap应由va_startva_copy宏初始化(无需干预va_end的调用)。每次调用va_arg宏都会修改ap,以便依次返回连续参数的值。参数类型应该是指定的类型名称,以便只需通过将*固定为类型即可获得指向具有指定类型的对象的指针的类型。 如果没有实际的下一个参数,或者type与实际的下一个参数的类型不兼容(如同提升的那样)   对于默认参数促销),行为未定义,除以下情况外:

     

- 一种类型是有符号整数类型,另一种类型是相应的无符号整数类型,并且该值可在两种类型中表示;

     

- 一种类型是指向void的指针,另一种是指向字符类型的指针。