我正在用GCC的-Wconversion警告标志构建我的项目。 (gcc(Debian 4.3.2-1.1)4.3.2)在64位GNU / Linux OS /硬件上。我发现它有助于确定我混合类型的位置或者应该使用哪种类型的清晰度。
在大多数激活它的警告的其他情况下,它并没有那么有用,我问我打算怎么处理这些问题:
enum { A = 45, B, C }; /* fine */
char a = A; /* huh? seems to not warn about A being int. */
char b = a + 1; /* warning converting from int to char */
char c = B - 2; /* huh? ignores this *blatant* int too.*/
char d = (a > b ? b : c) /* warning converting from int to char */
由于上述测试的意外结果(案例a
和c
),我也要求解释这些差异。
编辑:是否过度工程化以使用(char)
投射所有这些以防止警告?
Edit2:一些额外的案例(继上述案例之后):
a += A; /* warning converting from int to char */
a++; /* ok */
a += (char)1; /* warning converting from int to char */
除此之外,我要问的是主观的,我想听听其他人在你认为某些开发者主张删除所有警告时如何处理这类情况下的转换警告
YAE:
一种可能的解决方案是使用int
而不是char
s对吗?实际上,它不仅需要更多内存,而且速度也更慢,如下面的代码所示。数学表达式只是用-Wconversion
构建时获取警告。我认为使用char
变量的版本运行速度比使用int
的版本要慢,但是在我的(64位双核II)系统上,int
版本较慢。
#include <stdio.h>
#ifdef USE_INT
typedef int var;
#else
typedef char var;
#endif
int main()
{
var start = 10;
var end = 100;
var n = 5;
int b = 100000000;
while (b > 0) {
n = (start - 5) + (n - (n % 3 ? 1 : 3));
if (n >= end) {
n -= (end + 7);
n += start + 2;
}
b--;
}
return 0;
}
将-DUSE_INT
传递给gcc以构建上述代码段的int版本。
答案 0 :(得分:2)
当你说/* int */
时,你是说它会给你一个警告吗?我在这段代码中没有看到任何带有-Wconversion
的gcc 4.0.1或4.2.1的警告。编译器正在将这些枚举转换为常量。由于在编译时已知所有内容,因此没有理由生成警告。编译器可以优化所有不确定性(以下是英特尔4.2.1):
movb $45, -1(%rbp) # a = 45
movzbl -1(%rbp), %eax
incl %eax
movb %al, -2(%rbp) # b = 45 + 1
movb $44, -3(%rbp) # c = 44 (the math is done at compile time)
movzbl -1(%rbp), %eax
cmpb -2(%rbp), %al
jle L2
movzbl -2(%rbp), %eax
movb %al, -17(%rbp)
jmp L4
L2:
movzbl -3(%rbp), %eax
movb %al, -17(%rbp)
L4:
movzbl -17(%rbp), %eax
movb %al, -4(%rbp) # d = (a > b ? b : c)
这没有开启优化。通过优化,它将在编译时为您计算b和d并对其最终值进行硬编码(如果实际需要它们的话)。关键是gcc已经确定这里不存在问题,因为所有可能的值都适合char
。
b
的赋值可能存在错误,编译器永远不会捕获它,即使它是确定的。例如,如果b=a+250;
,那么肯定会溢出b
,但gcc不会发出警告。这是因为a
的赋值是合法的,a
是char
,并且确保数学运算不会在运行时溢出是您的问题(而不是编译器)。
答案 1 :(得分:0)
也许编译器已经可以看到所有值都适合char,所以它不会打扰警告。我希望在编译开始时解决enum
。