我问这个问题有两种不同的语言:C和C ++。
调用具有相反整数符号期望的函数时,最佳做法是什么?我们的代码需要什么?
例如:
uint32 _depth; // uint32 = DWORD
int depth;
_BitScanForward(&_depth, (uint32)input); // DWORD, DWORD
depth = (int)_depth;
_BitScanForward期待DWORD(uint32)参数。变量input
是int16类型,我需要在我的代码中将结果_depth
作为int32处理。
input
投射?我知道编译器会可能为我做,但最佳做法是什么?_depth
声明为int32是否可以接受,因此避免之后必须将其强制转换?注意:
我对编译器的评论是基于经验的。我编写的代码在VS中没有警告编译但在执行时崩溃。原来我正在调用一个incorect width int的函数。所以我不再将这个话题留给编译器了。
修改
答案很有帮助,谢谢。让我提炼我的问题。如果没有宽度问题,即函数不期望比传入的更窄的int(obvioulsy将失败),那么依靠编译器处理符号和宽度差异是否可以?
答案 0 :(得分:37)
我强烈建议将该函数隐藏到自定义包装函数中,该函数与您首选的API一致(并且在此函数中执行适当的显式转换)。在使用特定于编译器的函数的情况下,这具有额外的优点,即通过重新实现该包装函数,将它移植到不同的编译器(你是否想要这样做)会更容易。
答案 1 :(得分:9)
从任何比saveFooData()
窄的整数类型转换为宽度相同或宽于int
的任何整数类型时,编写显式转换非常重要。如果你不这样做,编译器将首先将值转换为int
,因为"整数提升"规则,然后到目标类型。这几乎总是错误的,如果我们今天从头开始,我们就不会以这种方式设计语言,但出于兼容性考虑,我们仍然坚持使用它。
系统提供的typedef(如int
,uint16_t
,uint32_t
和WORD
可能比DWORD
更窄,更宽或相同;在C ++中,你可以使用模板来解决它,但在C中你不能。因此,您可能希望为涉及这些的任何转换编写显式强制类型转换。
答案 2 :(得分:4)
那有点取决于你的用法等:
如果我可以使用所需类型,我只需使用类型。
如果没有: 在隐式转换可能导致上溢/下溢的数据类型的情况下,编译器应该警告您。所以我通常会有这些警告,并将隐式转换更改为显式转换。
我有两种不同的方法:
如果我100%确定我从未在签名/无符号int之间的边界上/下溢,我使用static_cast
。 (通常用于转换不同的API。比如size()返回int vs size_t)。
当我不确定或有可能时,我超出了我使用boost::numeric_cast
的界限。当你超越边界时会抛出异常,从而显示何时发生这种情况。
具有例外情况的方法遵循以下操作:如果出现问题而导致硬故障/崩溃/终止,而不是继续使用损坏的数据,然后在其他地方崩溃或使用未定义的数据执行其他操作。
答案 3 :(得分:1)
首先,您的编译器会隐式转换,并会在任何有意义的警告级别上发出警告。
您执行的两个强制转换都是强制转换,编译器(或您的同事)无法轻易确定它们是否正确,因此使用边界测试进行显式转换或显式转换是最佳做法。您选择哪种方法取决于您对数据的了解。最安全的方法是检查边界条件。最简单的方法是简单地转换(在C ++中请使用static_cast而不是C风格的转换)。