我正在阅读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 ++中导致执行中出现警告和错误?
答案 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