【问题标题】:Can't assign -2147483648 to variable of type long long无法将 -2147483648 分配给 long long 类型的变量
【发布时间】:2014-01-22 22:25:31
【问题描述】:

我正在编译下面的代码,由于某种原因,我无法将 -2147483648 分配给 8 字节长且有符号的变量。

long long x = -2147483648;

当我越过这条线时,x 的值为 2147483648,MS Visual Studio 中的“观察”窗口显示 x 的类型为 __int64。 sizeof(x) 也返回 8。

根据limit.h,有符号长长的限制是:

#define LLONG_MAX     9223372036854775807i64       /* maximum signed long long int value */
#define LLONG_MIN   (-9223372036854775807i64 - 1)  /* minimum signed long long int value */

和:

/* minimum signed 64 bit value */
#define _I64_MIN    (-9223372036854775807i64 - 1)
/* maximum signed 64 bit value */
#define _I64_MAX      9223372036854775807i64

我就是不明白!!!

有人可以解释一下吗?

【问题讨论】:

  • 我认为你只需要“LL”字面量。所以long long x = -2147483648LL;
  • @David:是的,MS Visual Studio。他们怎么了?
  • 那不是真正的 C 编译器。 C++ 编译器很好,但 C 编译器是 C89 的一些模糊近似,并不是一个很好的编译器。在 C 模式下编译时,所有赌注都关闭。
  • 对于 GCC 中的我来说,这段代码编译但产生了错误的结果:它的大小是正确的,但数字是 。我真的不明白。
  • 是的,这很奇怪。我希望有人能对此有所了解。

标签: c


【解决方案1】:

如果没有 LL,编译器似乎会推断出 2147483648 是 32 位 unsigned long然后它应用- 运算符。结果是0 - 2147483648。由于它小于 0 并且是 unsigned long t,因此添加了 4294967296,也就是 2147483648。然后将此值分配给long long x

建议:

long long x = -2147483648LL;
// or
long long x = -2147483647  - 1;

【讨论】:

    【解决方案2】:

    尝试分配给-2147483648LL

    请参阅整数常量here

    【讨论】:

    • 谢谢。但是为什么编译器不能自己弄清楚呢?类型明明是long long吧?
    【解决方案3】:

    您的代码在我的 GCC 4.6.3 编译器上编译并执行良好,使用 --std=c99。我怀疑您使用的是微软提供的相当绝望的所谓 C 编译器。这显然不是很聪明。使用长长的后缀(i64llLL)来欺骗它的行为。

    有趣的是,MS C++ 编译器也无法做到这一点:

    #include <iostream>
    int main()
    {
        long long x = -2147483647;
        std::cout << x << std::endl;
        x = -2147483648;
        std::cout << x << std::endl;
        x = -2147483649;
        std::cout << x << std::endl;
        return 0;
    }
    

    输出

    -2147483647 2147483648 2147483647

    我用 VS2013 的 x86 C++ 编译器编译了这个。

    我从我的 g++ 4.6.3 得到相同的输出。

    所以我认为这不仅仅是表面上看到的。我希望比我了解更多的人能解释这一切。

    【讨论】:

    • 哇。这太疯狂了。
    • 我也希望如此。我想更好地理解这一点。
    • 我能否请求您不接受我的回答。我不认为这是一个很好的答案。我希望比我更了解这些东西的人能过来并给出一个好的答案。
    【解决方案4】:

    回答其他一些 cmets(对不起,由于我还没有足够的代表,所以无法回复他们每个人):

    在 C 和 C++ 中,表达式的类型不依赖于其上下文。在这种情况下,-214743648 的类型由语言规则定义,您稍后将其分配给 long long 的事实不会影响这一点。

    实际上,这种做事方式使语言比替代方案简单得多,这是最初吸引我使用 C 的原因之一。

    在大卫赫弗南的例子中,

    x = -2147483648;
    std::cout << x << std::endl;     // gives 2147483648
    x = -2147483649;
    std::cout << x << std::endl;     // gives 2147483647
    

    重要的是- 符号不是整数文字的一部分。表达式2147483648是一个整数常量,其类型根据标准中的一组规则确定;然后将一元减号运算符应用于该值(不会改变其类型)。

    不幸的是,C90、C99、C++98 和 C++11 对整数字面量的类型都有不同的规则。此外,十进制常量的规则与十六进制或八进制常量的规则不同!您可以在相关的标准文档中查找它们。

    如果您有 32 位整数,则 2147483648 太大而不能成为 int。在所有方言中,下一个可能的类型是long int。如果您还有 32 位 long ints,那么在 C99 或 C++11 中它的类型为 long long int。在 C90 或 C++98 中,它的类型为 unsigned long int。 (那些语言没有long long 类型)。

    回到大卫赫弗南的例子。 C++98 没有long long,因此您要么使用 C++11 编译器,要么使用 Microsoft 扩展。假设后者;谁知道他们决定对整数常量做什么,但如果他们保留了 2147483648 的类型为 unsigned long int 的 C++98 定义,那将解释结果。

    【讨论】:

      【解决方案5】:

      原来我只需要这样写:

      long long x = -2147483648i64;
      

      为什么编译器无法弄清楚。我已经拼出了类型,为什么还要在数字后面加上'i64'???

      【讨论】:

      • 您可能使用的是旧编译器,或者 C 支持较差的编译器。
      • @Dietrich:我正在使用 MS Visual Studio 2012 附带的编译器。
      • 这就解释了。众所周知,Visual Studio 编译器对 C 语言的支持很差。其他编译器会自动计算出来,这是自 1999 年以来 C 规范所要求的。
      • @DietrichEpp 有趣的是,MS C++ 编译器也无法管理这个。
      • 根据其他人的帖子,看起来 GCC 也有类似的问题?
      猜你喜欢
      • 1970-01-01
      • 2011-10-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-24
      • 1970-01-01
      相关资源
      最近更新 更多