以下代码在 g++ 4.1.1 和-Wall
.
int octalStrToInt(const std::string& s)
{
return strtol(s.c_str(), 0, 8);
}
我期待一个警告,因为 strtol 返回 along int
但我的函数只返回一个 plain int
。其他编译器可能会在这里发出警告吗? 在这种情况下,我应该将返回值转换为 int 作为一种好习惯吗?
最好的方法是:
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
(我不知道如何读取八进制)和 stringstream。阅读您想要的类型,而不是恰好具有 C 库函数的类型。
您可能需要 -Wconversion 标志来打开这些警告。但是,它不会警告long -> int,因为它们的大小与 GCC 相同(值不会因为转换而改变)。但是,如果您转换例如long -> short
我想不建议简单地进行演员表,因为那只会掩盖错误的可能性。在您检查过这样的强制转换不会修改该值以安抚编译器之后就可以了。
您在这里看不到任何警告,因为您平台上的“int”和“long int”数据类型具有相同的大小和范围。根据架构,它们可能会变得不同。
为了保护自己免受奇怪错误的影响,请使用范围检查。我建议您使用 std::numeric_limits::min/max(参见 参考资料)。
范围检查后,您可以安全地使用 static_cast 或 c 样式转换。
另一方面,您可以依赖 std::stringstream 类中实现的相同功能。默认情况下,使用 std::stringstream 的转换将是平台安全和类型安全的。
大多数现代编译器会根据您配置的警告级别警告转换和可能的截断。在 MSVC 上是警告级别 4。
最佳实践是从您的函数中返回一个 long,并让调用代码决定如何处理转换。除此之外,至少要确保从 strtol 返回的值在返回之前适合 int,正如 Let_Me_Be 所建议的那样。