我刚刚读到了关于铸造返回值的不良做法malloc
.如果我理解正确的话,离开演员是绝对合法的,因为它是隐含的(并且应该留下,因为它可能产生其他问题).那么我的问题是,我什么时候应该施展我的价值观呢?有一些一般规则或什么?例如,此代码编译时没有任何错误gcc -W -Wall
(除了未使用bar
,但这不是重点):
float foo(void) { double bar = 4.2; return bar; } int main(void) { double bar = foo(); return 0; }
我现在很困惑.有关铸造的良好做法和规则是什么?
谢谢.
有几种情况需要在C中进行完全有效的铸造.要注意像"铸造总是糟糕的设计"这样的清晰断言,因为它们明显而且显然是虚假的.
严重依赖演员表的一大群情境是算术运算.当您需要强制编译器解释与"默认"类型不同的类型中的算术表达式时,需要进行转换.如在
unsigned i = ...; unsigned long s = (unsigned long) i * i;
避免溢出 或者在
double d = (double) i / 5;
为了使编译器切换到浮点除法.或者在
s = (unsigned) d * 3 + i;
为了取整个浮点值的一部分.等等(例子是无穷无尽的).
另一组有效用途是成语,即完善的编码实践.例如,当一个函数将一个const指针作为一个输入并返回一个非const指针指向同一个(可能是常量的)数据时,例如标准的经典C语言strstr
.实现这个习惯用法通常需要使用强制转换来抛弃输入的常量.有人可能称之为糟糕的设计,但实际上在C中没有更好的设计选择.否则,它不会是一个成熟的成语:)
另外值得一提的是,作为一个例子,标准printf
函数的迂腐正确使用可能需要在一般情况下对参数进行强制转换.(就像%p
格式说明符期望void *
指针作为参数一样,这意味着int *
必须以void *
某种方式将参数转换为a .显式转换是执行转换的最合理方式.).
当然,在需要强制转换时,还有其他众多完全有效的情况.
当人们不加思索地使用它们时,通常会出现演员表的问题,即使在不需要它们的情况下也是如此(例如,投票的回报malloc
,其原因多于一个).或者当人们使用强制转换来强制编译器接受他们的错误代码时.毋庸置疑,从一个糟糕的演员表中讲出一个有效的演员情况需要一定的专业水平.
在某些情况下,强制转换用于使编译器停止发出一些恼人的和不必要的警告消息.这些演员阵容属于好人和坏人之间的灰色区域.一方面,不必要的演员阵容很糟糕.另一方面,用户可能无法控制编译设置,因此使转换成为处理警告的唯一方法.
如果你需要演员,我总是建议你明确地这样做,以向别人展示,或者将来你自己也可以表明你想要这种行为.
顺便说一句,gcc警告是这样的-Wconversion
.不幸的是-Wall和-Wextra仍然留下了很多好的警告.
下面是我希望gcc非常像lint时使用的标志
-pedantic -std=c99 -ggdb3 -O0 -Wall -Wextra -Wformat=2 -Wmissing-include-dirs -Winit-self -Wswitch-default -Wswitch-enum -Wunused-parameter -Wfloat-equal -Wundef -Wshadow -Wlarger-than-1000 -Wunsafe-loop-optimizations -Wbad-function-cast -Wcast-qual -Wcast-align -Wconversion -Wlogical-op -Waggregate-return -Wstrict-prototypes -Wold-style-definition -Wmissing-prototypes -Wmissing-declarations -Wpacked -Wpadded -Wredundant-decls -Wnested-externs -Wunreachable-code -Winline -Winvalid-pch -Wvolatile-register-var -Wstrict-aliasing=2 -Wstrict-overflow=2 -Wtraditional-conversion -Wwrite-strings
我还首先使用cppcheck检查我的代码,cppcheck是一个用于C和C++的免费静态代码分析器.强烈推荐.