在我当前的项目中,编译器会显示数百条有关类型转换的警告。
有很多像这样的代码
iVar = fVar1*fVar2/fVar3;
// or even
iVar = fVar1*fVar2/fVar3+.5f;
故意将float
值分配给int
。
当然,我可以使用
修复这些警告iVar = (int)(...);
但这看起来很丑陋。
你宁愿生活在丑陋中还是与警告一起生活? 还是有一个干净的解决方案?
答案 0 :(得分:12)
有数百个不是问题的警告是危险的,有一天警告会出现真正的问题并淹没在噪音中。
保持代码免受警告。
如果您知道自己在做什么,请添加演员表或转换。
答案 1 :(得分:10)
是
您应该始终修复编译器警告。有几个原因:
*)它可能是错误的原因,需要一个实际的修复,而不仅仅是一个演员。直到你看,你才会知道。
*)显示为警告的实际编码错误可能会因数百次警告产生的噪音而丢失
*)它向其他编码员明确表示你确实打算在那里使用错误类型/符号的变量。这是故意的。
*)它清楚明确地表明正在改变类型和/或签名。如果您的变量名称不包含类型和签名的指示,则可能不会发生这种情况。
答案 2 :(得分:5)
我编译时将“警告视为错误”。警告通常是您编写代码的指标,这些代码不会按照您的预期方式运行。
在这种情况下,演员表明你正在改变类型,这意味着精度的变化(以及性能影响,如果你恰好处理极其时间关键的代码)。编写代码以最明显的方式显示所有显式和隐式结果始终是一个很好的策略,这样您几个月后就可以知道代码的作用 - 或者如果团队成员必须使用它。 / p>
答案 3 :(得分:2)
在我看来,有时编译器会针对我认为没有问题的问题发出警告。在这种情况下,解决方案可能是关闭那些特定的警告。但是你必须谨慎行事,并确保你也没有隐藏重要的警告。
对于隐式类型转换警告,您需要一些时间,但不是所有时间。通常,您希望忽略int到float转换,但是要听听其他转换。理想情况下,编译器允许您在该粒度级别配置警告报告。
答案 4 :(得分:1)
为任何缩小的隐式类型转换启用警告是个好主意,也就是说,转换后的类型无法保存原始类型的所有值的任何转换。这包括例如float to int转换,以及signed int和unsigned int之间的任意方向的转换。这些转换可能会导致信息溢出和/或丢失,因此应始终明确说明这些转换。
答案 5 :(得分:1)
在浮点到整数转换的情况下,我认为编写和使用函数而不是类型转换更好;函数本身可能会使用类型转换,但我会考虑调用像int_round_mid_up(x)
这样的函数比(int)(x+0.5)
更好,特别是因为函数可以很容易地写入一次,以正确处理正数和负数包括其他危险的0.499999999999999944 [当加到0.5时,产生1.0],而基于类型转换的表达式(int)(x+0.5)
将错误地舍入-2.4到-1。恕我直言,一种语言没有很好的方法来定义浮点到整数的类型转换(一些使用各种形式的舍入,一些截断,有些可能使用地板;因为没有明确的“最佳”方式进行转换,最好是要求程序员指定所需的东西而不是语言选择方法,因此程序员应该在非常狭窄的环境之外避免它们。
关于整数类型之间的转换,关于缩小转换的警告通常是好的,应该全局启用,但是通过显式类型转换在本地扼杀。对于大多数类型的数字工作,从double
到float
的转换通常不应生成警告(或更糟糕的是,错误),但遗憾的是并非所有语言或编译器都允许这些警告被扼杀,而不是其他类型。
应该设置为支持它的编译器生成警告的转换类别(尽管很多人不这样做)是从可能产生截断结果的窄表达式转换为能够保存结果的类型如果没有被截断,例如
uint64_t ul = ui1 - ui2; // With ui1 and ui2 being uint32_t
double d1 = f1 / f2; // With f1 and f2 being float
如果我想要上述表达式产生的行为,我会把它们写成:
uint64_t ul = (uint32_t)(ui1 - ui2);
double d1 = (float)(f1 / f2);
因为否则程序员在没有类型转换的情况下看到上述内容可能会倾向于将它们重写为:
uint64_t ul = (uint64_t)ui1 - ui2;
double d1 = (double)f1 / f2;
这会产生一些行为,虽然更典型的可取,但可能与程序实际需要的行为相反。