【问题标题】:Promotion of integer in variadic functions在可变参数函数中提升整数
【发布时间】:2016-10-20 05:34:00
【问题描述】:

为什么下面代码中的第一个f() 调用最终会打印出我作为4294967294 传递给它的-2

#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() 调用会导致这个问题。你能解释一下这种行为吗?

【问题讨论】:

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


    【解决方案1】:

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

    来自 Section 7.16.1.1/2 C11 标准(重点是我的):

    va_arg 宏扩展为具有指定类型和调用中下一个参数的值的表达式。参数ap 应已由va_startva_copy 宏初始化(没有va_end 的介入调用)。每次调用va_arg 宏都会修改ap,以便依次返回连续参数的值。参数类型应该是一个指定的类型名称,这样指向具有指定类型的对象的指针的类型可以简单地通过在类型后面加上 * 来获得。 如果没有实际的下一个参数,或者类型与实际的下一个参数的类型不兼容(根据提升 到默认参数提升),行为未定义,除了以下情况:

    ——一种是有符号整数类型,另一种是对应的无符号整数类型,值在两种类型中都是可表示的;

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

    【讨论】:

      猜你喜欢
      • 2016-07-15
      • 2021-05-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多