【问题标题】:Smallest values for int8_t and int64_tint8_t 和 int64_t 的最小值
【发布时间】:2013-04-16 09:20:23
【问题描述】:

关于在stdint.h 中找到的那些定义,我想测试一个函数,用于将int8_t 的向量或int64_t 的向量转换为std::string 的向量。

这是我的测试:

TEST(TestAlgorithms, toStringForInt8)
{
    std::vector<int8_t> input = boost::assign::list_of(-128)(0)(127);
    Container container(input);
    EXPECT_TRUE(boost::apply_visitor(ToString(),container) == boost::assign::list_of("-128")("0")("127"));
}

TEST(TestAlgorithms, toStringForInt64)
{
    std::vector<int64_t> input = boost::assign::list_of(-9223372036854775808)(0)(9223372036854775807);
    Container container(input);
    EXPECT_TRUE(boost::apply_visitor(ToString(),container) == boost::assign::list_of("-9223372036854775808")("0")("9223372036854775807"));
}

但是,我在 Visual Studio 中收到了一条警告:

std::vector<int64_t> input = boost::assign::list_of(-9223372036854775808)(0)(9223372036854775807);

如下:

warning C4146: unary minus operator applied to unsigned type, result still unsigned

如果我将 -9223372036854775808 更改为 -9223372036854775807,警告就会消失。

这里有什么问题?关于我的原始代码,测试通过了。

【问题讨论】:

  • 您是否也尝试过-9223372036854775808ll?正如 Bo Persson 所建议的,无论如何你都应该使用 std:numeric_limits。

标签: c++


【解决方案1】:

就像编译器说的那样,-9223372036854775808 不是有效数字,因为 - 和数字是分开处理的。

您可以尝试-9223372036854775807 - 1 或改用std::numeric_limits&lt;int64_t&gt;::min()

【讨论】:

  • +1 for std::numeric_limits&lt;int64_t&gt;::min(),这是最简洁、最具表现力、便携的方式。
  • @DevSolar 这当然更干净,更有表现力。然而,关于可移植性:int64_t 必须是 64 位,2 的补码表示,这意味着它在任何地方都将具有完全相同的最小值。
  • @JamesKanze:是的,但是-9223372036854775808 是一种写入最小值的非便携式方式(因为在使用 2 的补码 64 位 long long 的实现上,它调用实现定义的 unsigned- >签名转换)而std::numeric_limits&lt;int64_t&gt;::min()是一种可移植的方式。我认为-9223372036854775807 - 1 也是不可移植的,但仅在long long 是符号幅度的假设系统上失败(因此算术在常量表达式中溢出并被诊断),而int64_t 是一些扩展的2的补码整数类型。
  • @SteveJessop 好点。另一种可移植的方式是UINT64_MIN,它也非常易读——在某些情况下,它也可以作为一个整体 const 表达式的优势,尽管 C++11 在std::numeric_limits 中也修复了这个问题(和整体 const表达与否,我怀疑int a[UINT64_MAX]; 会起作用)。
  • @JamesKanze:是的,我个人更喜欢可以使用它们的宏(几乎每当整数类型不是模板参数或用auto / decltype 推导时)。 INT64_MIN 等还有一个(可疑的)优势,您可以在预处理器表达式中使用它们。
【解决方案2】:

问题是整数文字不是负数;所以-42 不是带有负值的文字,而是应用于文字42- 运算符。

在这种情况下,9223372036854775808 超出了int64_t 的范围,所以它会被赋予一个无符号类型。由于模运算的魔力,你仍然可以取反,赋值给int64_t,最终得到你期望的结果;但是编译器会警告您有关无符号否定(如果您告诉它),因为这通常是错误的结果。

您可以改用std::numeric_limits&lt;int64_t&gt;::min() 来避免警告(并使代码更明显正确)。

【讨论】:

    【解决方案3】:

    -9223372036854775808 更改为-9223372036854775807-1

    问题是 -9223372036854775808 不是 -9223372036854775808 而是 -(9223372036854775808)9223372036854775808 不能适应有符号的 64 位类型(默认情况下十进制整数常量是有符号类型),所以它改为未签名。将- 的否定应用于无符号类型是可疑的,因此会出现警告。

    【讨论】:

      猜你喜欢
      • 2015-09-22
      • 2015-10-19
      • 1970-01-01
      • 1970-01-01
      • 2013-07-18
      • 2022-11-12
      • 2023-04-02
      • 2014-03-22
      相关资源
      最近更新 更多