题
以下代码不会给G ++ 4.1.1和 -Wall
.
int octalStrToInt(const std::string& s)
{
return strtol(s.c_str(), 0, 8);
}
我期待警告,因为Strtol返回 long int
但是我的功能只是返回平原 int
. 。其他编译器会在这里发出警告吗? 在这种情况下,我应该将回报价值视为一个好习惯吗?
解决方案
您可能需要-wconversion标志来打开这些警告。但是,它不会警告 长 -> int, ,由于它们与GCC的大小相同(由于转换而不会改变值)。但是,如果您转换为 长 -> 短的
我想不建议这样做,因为这只会掩盖虫子的可能性。在检查这样的演员不会修改值以安抚编译器的值之后,还可以。
其他提示
最好的方法是:
long x = strtol(...); assert(x <= INT_MAX); return (int)x;
你需要 limits.h
和 assert.h
如果您无法访问 boost::numeric_cast
, ,您可以写一个简单的模仿:
template <typename T, typename S>
T range_check(const S &s) {
assert(s <= std::numeric_limits<T>::max());
assert(s >= std::numeric_limits<T>::min());
return static_cast<T>(s); // explicit conversion, no warnings.
}
return range_check<int>(strtol(some_value,0,8));
实际上,这有点作弊,因为它不适用于浮点目的地类型。 min()
对于它们而言,与整数类型的绑定不是相同的,您需要检查+/- max()
. 。为读者锻炼。
无论您使用断言还是其他错误处理取决于您实际上想做的无效输入。
还有 boost::lexical_cast
(我不知道该如何使该读取八元读)和弦乐。阅读您想要的类型,而不是恰好具有C库功能的类型。
您在这里看不到任何警告,因为平台上的“ int”和“ long int”数据类型具有相同的尺寸和范围。根据建筑的不同,它们可能会与众不同。
为了保护自己免受奇怪的错误,请使用范围检查。我建议您使用std :: numeric_limits :: min/max(请参阅)。
范围检查后,您可以安全地使用static_cast或c风格铸件。
另一方面,您可以依靠STD :: Stringstream类中实现的相同功能。默认情况下,使用STD :: stringstream的转换将是平台安全和类型安全。
大多数现代编译器都会根据您配置的警告级别警告转换和可能的截断。在MSVC上是警告4。
最佳实践是从您的功能中返回长时间,并让呼叫代码决定如何处理转换。除此之外,至少要确保您从strtol中获得的价值在返回之前将适合INT,如LET_ME_BE所建议。