我需要将strtol的结果转换为int吗?

时间:2010-03-11 14:36:13

标签: c++ casting strtol

以下代码未向g ++ 4.1.1和-Wall发出警告。

int octalStrToInt(const std::string& s)
{    
    return strtol(s.c_str(), 0, 8);
}

我期待一个警告,因为strtol返回long int,但我的函数只返回一个普通的int。其他编译器可能在这里发出警告吗? 在这种情况下,我应该将返回值转换为int作为一种好习惯吗?

5 个答案:

答案 0 :(得分:3)

最佳方法是:

long x = strtol(...); assert(x <= INT_MAX); return (int)x;

您需要limits.hassert.h

答案 1 :(得分:2)

如果您无法访问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()。为读者练习。

是否使用assert或其他一些错误处理取决于您对无效输入的实际想要做的事情。

还有boost::lexical_cast(副手我不知道如何制作读取八进制)和stringstream。读取您想要的类型,而不是具有C库函数的类型。

答案 2 :(得分:1)

您可能需要-Wconversion标志才能启用这些警告。但是,它不会警告 - &gt; int ,因为它们与GCC的大小相同(由于转换,值不会改变)。但是,如果您转换为 long - &gt;的

我认为不建议单独进行演员表演,因为那只会掩盖错误的可能性。在检查出这样的强制转换不会修改值以安抚编译器之后就可以了。

答案 3 :(得分:1)

您在此处看不到任何警告,因为您平台上的“int”和“long int”数据类型具有相同的大小和范围。根据架构,它们可能会变得不同。

为了保护自己免受奇怪的错误,请使用范围检查。我建议你使用std :: numeric_limits :: min / max(参见参考资料)。

在范围检查后,您可以安全地使用static_cast或c-style cast。

另一方面,您可以依赖std :: stringstream类中实现的相同功能。默认情况下,使用std :: stringstream进行转换将是平台安全且类型安全的。

答案 4 :(得分:0)

大多数现代编译器会根据您配置的警告级别警告转换和可能的截断。在MSVC上,警告级别为4。

最佳做法是从函数返回long,并让调用代码决定如何处理转换。除非如此,至少要确保从返回之前返回的值与strtol的值相符,如Let_Me_Be所示。