【问题标题】:Visual Studio 2015 - Compiler Warning (level 2) C4146Visual Studio 2015 - 编译器警告(2 级)C4146
【发布时间】:2016-04-28 22:47:18
【问题描述】:

我的代码中有以下行

signed int test_case= -2147483648;

产生错误:

C4146 一元减号运算符应用于无符号类型,结果仍然无符号

但这仍然是有符号整数类型的数据范围:

__int32 signed, signed int, int –2,147,483,648 到 2,147,483,647

奇怪的事情是将它分配为 signed long 给出了同样的错误,即

signed long test_case= -2147483648;

下面的修改编译OK:

signed int test_case= -2147483647;

signed int test_case= 2147483649;

signed long test_case= -214748364800;
  • 有人在 Visual Studio 2015 编译器中看到过这个问题吗?
  • 如何定义数据类型?
  • 如何检查范围?
  • 为什么它似乎忽略了“签名”分配?

谢谢

【问题讨论】:

  • 你自己写的:2,147,483,647 是最大的int,所以2,147,483,648(应用了-)不再是intsigned long long test_case = -2147483648ll;

标签: c++ visual-studio visual-studio-2015 language-lawyer compiler-warnings


【解决方案1】:

这是一个编译器错误。

首先要注意:-2147483648 不是文字。 C++ 中没有否定字面量。

-2147483648 是一个编译时可评估的常量表达式,由 2147483648 和一元减号运算符组成。

在面向 Windows x64(其中 int 和 long 都是 32 位)的 MSVC 上,2147483648 应该long long int,因此 -2147483648 也是如此。我的理解是,标准 坚持 有符号类型除非您使用十六进制或八进制文字。

在这种情况下,到 signed int 的缩小转换是明确定义的,因为您的目标是具有 32 位 2 的补码 int 类型的平台。

更多参考:见http://en.cppreference.com/w/cpp/language/integer_literal

【讨论】:

  • 我不明白你的意思。 2147483648 对于 32 位签名来说太大了,所以标准坚持使用 long long int。
  • 啊!对不起对不起我现在得到你
  • 你的意思是标准规定如果 int 不适合的下一个级别是 long long 而不是 int 的无符号版本?
  • 确实如此。它不能使用无符号类型,除非你用十六进制或八进制表示法编写了文字。见en.cppreference.com/w/cpp/language/integer_literal的“无后缀”部分
  • 有趣!在 MSDN 中,他们明确表示这是有意为之的事情!
【解决方案2】:

因为它是一个编译器错误,这个答案是特定于 MSVC 的,从 iso C++ 的角度来看它是 错误。对于正确和标准的答案,请参阅@Bathsheba 答案。(我鼓励 OP 为未来的读者接受正确答案而不是这个答案)。


来自MSDN

对数字 2147483648 求值。因为它大于 2147483647的最大整数值,2147483648的类型不是 整数,但无符号整数。

换句话说,编译器会将 -2147483648 处理为 -2147483648 而不是 -2147483648。因此2147483648 部分被视为unsigned int,因为它大于int。然后编译器应用导致此警告的- 运算符。

解决方案:

auto test_case= -2147483648ll;

【讨论】:

  • 但我正在尝试分配一个负数 -2147483648
  • 没有什么叫做负数。它是 int (或单位)和减一元运算符。查看我的编辑
  • OK.... 那么如何分配-2147483648 仍然在所分配变量的数据类型范围内呢?
  • int a = -2147483648ll;
  • 太棒了!这样可行。为什么signed long test_case= -214748364800; 不会产生同样的错误?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-05
  • 2022-06-10
  • 1970-01-01
  • 2016-10-25
  • 1970-01-01
相关资源
最近更新 更多