'stol' 使用 Visual Studio 而不是 gcc 引发的异常

Exception thrown by 'stol' using Visual Studio but not gcc

以下代码在 Visual Studio 2013 下 运行 而不是 gcc 4.9.2 时抛出异常。

报告的错误是:

'exception: stol argument out of range'

stol returns a long 因此 temp 的大小应该足以容纳返回值。

任何人都可以解释这种行为。这可能是编译器错误吗?

#include <iostream>
#include <exception>
#include <string>
#include <stdexcept>

int main()
{
    const std::string value = "4294967295";   // 0xffffffff

    try
    {
        int64_t temp = std::stol(value);
    }

    catch (std::invalid_argument& ex)
    {
        std::cout << "invalid_argument: " << ex.what() << "\n";
    }

    catch (std::exception& ex)
    {
        std::cout << "exception: " << ex.what() << "\n";
    }

   return 0;
}

我的赌注是 visual studio 上的 32 位 long(最大 2^31,所以溢出)和 GCC 上的 64 位 long(所以离溢出还差得很远)。

来自

http://en.cppreference.com/w/cpp/string/byte/strtol

strtol returns long 需要 strtoll 才能得到 long long

在 Windows 下,类型 long 总是 32 位。由于 long 是有符号整数类型,这意味着 long 的范围在 -2147483648 和 2147483647 之间(含)。在 Linux 上,long 的大小取决于您是针对 32 位还是 64 位进行编译。

由于 std:stol 将字符串转换为 long,因此结果必须适合 long。如果不是,则函数 throws std::out_of_range。要解决此问题,您可以使用 std::stoll which returns a long long,保证至少为 64 位,因此在转换 [=20= 时不会抛出异常].您还可以使用 std::stoul,它转换为 unsigned long,保证范围至少为 0 到 4294967295。

(请注意,这并不是严格意义上的 Visual C++ 与 GCC 的对比。当以 Windows 为目标时,GCC 也始终使用 32 位 long。)

不是编译器错误,问题是您的假设无效。

标准允许 LONG_MAX 低至 2147483647,因此

stol returns a long so the size of temp should be big enough to hold the value.

根本不是真的。

所以只需使用 std::stoul 即可。

乍一看,字符串常量肯定超过了 long 可以假设的最大值,但没有超过 unsigned long 可以假设的最大值...