我正在阅读《 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 ++中导致执行过程中出现警告和错误?
函数的可变参数要进行称为默认参数提升的转换:转换级别小于传递给可变函数之前int
被提升为的所有东西int
。并且enum
转换等级较小(short
在您的情况下,可以用或表示)。因此,您的被呼叫者看到的是一个int,必须这样来获取它va_arg
。
C99 7.15.1.1 p.2(强调我的)关于va_arg
:
[…]如果没有实际的下一个自变量,或者类型与实际的下一个自变量的类型不兼容(根据默认自变量Promotions的提升),则该行为是不确定的,除了以下情况:
- 一种类型是有符号整数类型,另一种类型是相应的无符号整数类型,并且值在两种类型中都可以表示;
- [某事。关于指针类型]
6.7.2.2,第4页:
每个枚举类型应与char,有符号整数类型或无符号整数类型兼容。类型的选择是实现定义的,[…]
因此,该va_arg(ap, enum drink)
版本没有定义的行为(就C标准而言)。至少,如果编译器未指定始终int
用于enum
s。因此来自的警告gcc
。
一些编码准则说,要避免enum
完全使用类型,而要int
在各处使用并且仅定义enum
常量:
enum {
MUDSLIDE, FUZZY_NAVEL, MONKEY_GLAND, ZOMBIE
};
和
double price(int d);
高温超导
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句