【问题标题】:long long in C/C++C/C++ 中的 long long
【发布时间】:2010-11-30 08:15:15
【问题描述】:

我正在 GNU 的 C++ 编译器上尝试此代码,但无法理解其行为:

#include <stdio.h>;

int main()
{
    int  num1 = 1000000000;
    long num2 = 1000000000;
    long long num3;
    //num3 = 100000000000;
    long long num4 = ~0;

    printf("%u %u %u", sizeof(num1), sizeof(num2), sizeof(num3));
    printf("%d %ld %lld %llu", num1, num2, num3, num4);
    return 0;
}

当我取消注释注释行时,代码无法编译并给出错误:

错误:整数常量对于长类型来说太大

但是,如果代码按原样编译并执行,它会产生远大于 10000000000 的值。

为什么?

【问题讨论】:

  • 现在可能为时已晚,但对于未来的读者,我建议您使用&lt;stdint.h&gt; 并使用uint64_t。要显示 64 位值,printf( "%" PRIu64 "\n", val);
  • @morticgeek &lt;stdint.h&gt; 包括在内,uint64_t a = 0xffffffffffffff; printf( "%" PRIu64 "\n",a ); : error: expected ‘)’ before ‘PRIu64’ printf( "%" PRIu64 "\n",a ); :: warning: spurious trailing ‘%’ in format [-Wformat=] printf( "%" PRIu64 "\n",a );
  • #define __STDC_FORMAT_MACROS 1stackoverflow.com/questions/14535556/…

标签: c++ types long-integer


【解决方案1】:

字母 100000000000 构成一个字面整数常量,但对于 int 类型而言,该值太大。您需要使用后缀来更改文字的类型,即

long long num3 = 100000000000LL;

后缀LL 使文字变成long long 类型。 C 不够“聪明”,无法从左侧的类型得出结论,类型是文字本身的属性,而不是使用它的上下文。

【讨论】:

  • 回到写这个答案的时候它可能是正确的,但是现在 C++ 标准说没有后缀的整数文字的类型是 intlong int 和 @987654328 中的第一个@ 在其中可以表示其值。 [C++ §2.14.2/2] 因此,现在无需将“LL”后缀添加到对于其他类型来说太大的整数文字。
  • 之前这是一个问题的原因并不是因为 C++ 不够“聪明”,无法从分配给的变量的类型中确定字面量类型,而仅仅是因为编译器extension 没有实现扩展的整数类型,因此它可以很好地与标准语言一起使用。 C++ 现在有规则使得任何扩展的整数类型都可以更好地与标准集成:open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1988.pdf
  • @unwind 我认为应该根据这些建议编辑答案。
【解决方案2】:

试试:

num3 = 100000000000LL;

顺便说一句,在 C++ 中这是一个编译器扩展,标准没有定义 long long,这是 C99 的一部分。

【讨论】:

  • 好吧,C++11 现在定义了 long long
【解决方案3】:

这取决于您正在编译的模式。 long long 不是 C++ 标准的一部分,但仅(通常)支持作为扩展。这会影响文字的类型。没有任何后缀的十进制整数文字总是 int 类型 如果 int 足够大 来表示数字,否则为 long。如果这个数字对于 long 来说太大,结果是实现定义的(可能只是为了向后兼容而截断的一些 long int 类型)。在这种情况下,您必须显式使用 LL 后缀来启用 long long 扩展(在大多数编译器上)。

下一个 C++ 版本将正式支持 long long,除非您明确希望强制字面量的类型至少为 long long,否则您不需要任何后缀。如果数字不能用 long 表示,即使没有 LL 后缀,编译器也会自动尝试使用 long long。我相信这也是 C99 的行为。

【讨论】:

    【解决方案4】:

    您的代码在这里编译得很好(即使该行未注释。必须将其更改为

    num3 = 100000000000000000000;
    

    开始收到警告。

    【讨论】:

    • 什么编译器?在 C++ 中,整数文字是 int 或 long 中较小的一个。在 C99 中,它是 int、long、long long 中的最小值。因此,当长期将 C++ 用作非标准扩展时,也许您的编译器也采用了 C99 文字规则。
    • gcc 版本 4.3.2 (Debian 4.3.2-1.1) 在 64 位 linux 系统上。
    • @SteveJessop 可能有点晚了:但 long 不一定是 64 位。大多数时候它是,但你不能保证它会无处不在。唯一的保证是它至少和 int 一样大,而 int 又至少和 short int 一样大,而 short int 又至少和 char 一样大。最后,char 被定义为足够大以表示实现的基本字符集中的每个字符(通常为 8 位)。
    • @pauluss86:我不是在谈论保证。 Omry 说他在 64 位 Debian 系统上使用 gcc 4.3.2。我观察到这解释了他所看到的(我碰巧知道作为常识)在此类系统上默认配置 gcc 以使用符合该操作系统的 LP64 ABI 的 64 位 long
    • @SteveJessop 我并不是说你的评论是错误的!只是指出假设 long 总是 64 位,不幸的是很多人认为这是危险的。
    【解决方案5】:

    注意:

    1. 去掉头文件后的分号
    2. 使用 %lu 而不仅仅是 %u
    3. long long num3 = 100000000000LL;

    更换这些东西,你就可以开始了:)

    【讨论】:

    • 您的第二点不正确。 OP 对%u 的使用与sizeof(...) 的结果一致——即std::size_tsize_t 的正确格式说明符是 %zu。此外,这个问题已经得到充分的回答 10 多年,并且这个答案没有扩展或提供任何不同的细节到 OP 的问题(实际上,它提供的信息较少)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-05-08
    • 1970-01-01
    • 1970-01-01
    • 2011-09-13
    • 2011-08-06
    • 1970-01-01
    相关资源
    最近更新 更多