传递错误" enum"在具有可变参数的函数中

时间:2014-07-04 20:36:22

标签: c arguments

我正在阅读Head First C这本书,我是变量参数的一部分。

我写了以下代码:

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>

enum drink {
    MUDSLIDE, FUZZY_NAVEL, MONKEY_GLAND, ZOMBIE
};

double price(enum drink d) {
    switch(d) {
    case MUDSLIDE:
        return 6.79;
    case FUZZY_NAVEL:
        return 5.31;
    case MONKEY_GLAND:
        return 4.82;
    case ZOMBIE:
        return 5.89;
    }
    return 0;
}

double calc(int args, ...) {
    double total = 0;

    va_list ap;
    va_start(ap, args);

    int i;
    for (i = 0; i < args; i++) {
        int currentDrink = va_arg(ap, int);
        total += price((drink) currentDrink);
    }

    va_end(ap);
    return total;
}

int main() {
    printf("Price is %.2f\n", calc(2, MONKEY_GLAND, MUDSLIDE));
    return 0;
}

代码编译完美。

但是......我的解决方案有两个不同的方面。

int currentDrink = va_arg(ap, int);
total += price((drink) currentDrink);

图书:

enum drink currentDrink = va_arg(ap, enum drink);
total += price(currentDrink);

我尝试使用本书中提出的解决方案,但执行过程中出现错误并报告警告:'drink'在通过'...'时被提升为'int'

本书在linux上使用gcc编译器。我在Windows上使用gcc。

问题:我无法编译本书中提出的代码的原因是什么?

修改 配置错误。使用C ++编译器是考虑使用C语言。 但问题仍然存在:为什么在C ++中导致执行中出现警告和错误?

1 个答案:

答案 0 :(得分:4)

函数的变量参数受到称为默认参数促销的转换的影响:转换等级小于int的所有内容在传递给int之前都会被提升为enum可变函数。 short的转化次数较小(在您的案例中可能表示为va_arg或其他内容)。所以你的被调用者看到的是一个int,必须按va_arg来获取它。

C99 7.15.1.1 p.2(强调我的)关于va_arg(ap, enum drink)

  

[...]如果没有实际的下一个参数,或者type与实际的下一个参数的类型不兼容(根据默认参数promotion 提升),则行为未定义,除以下情况外:

     
      
  • 一种类型是有符号整数类型,另一种类型是相应的无符号整数类型,并且该值可在两种类型中表示;
  •   
  • [某物。关于指针类型]
  •   

和6.7.2.2,第4页:

  

每个枚举类型应与char,有符号整数类型或无符号整数类型兼容。类型的选择是实现定义的,[...]

因此,int版本没有定义的行为(就C标准而言)。至少,如果编译器没有指定始终对enum使用gcc。因此来自enum的警告。

一些编码指南说要完全避免使用int类型,在任何地方使用enum并且只定义enum { MUDSLIDE, FUZZY_NAVEL, MONKEY_GLAND, ZOMBIE }; 常量:

double price(int d);

{{1}}

HTH