在C / C ++中很久很久


84

我正在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大得多的值。

为什么?


8
现在可能为时已晚,但对于将来的读者,建议您使用<stdint.h>和使用uint64_t。要显示一个64位的值,printf( "%" PRIu64 "\n", val);
enthusiasticgeek

@enthusiasticgeek,<stdint.h>包括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 );
牧民

Answers:


147

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

long long num3 = 100000000000LL;

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


47
回来时,这个答案写它可能是正确的,但现在的C ++标准说,没有后缀一个整数文字的类型是第一的intlong int以及long long int在其值可表示。[C ++§2.14.2/ 2]因此,现在无需将'LL'后缀添加到对于其他类型而言太大的整数文字中。
bames53 2012年

8
以前这是一个问题的原因并不是因为C ++不够“聪明”,无法从分配给变量的类型确定文字类型,这仅仅是因为编译器扩展未实现扩展整数使其适合标准语言。C ++现在有规则,以便任何扩展的整数类型都可以更好地与标准集成:open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1988.pdf
bames53 2012年

4
@unwind我认为答案应该根据这些建议进行编辑。
2013年


4

这取决于您以哪种模式进行编译。long long不是C ++标准的一部分,而是(通常)仅作为扩展支持。这会影响文字的类型。如果int足够大以表示数字,则不带任何后缀的十进制整数常量始终为int类型,否则为long。如果该数字甚至太长了,那么结果是实现定义的(可能只是为了向后兼容而被截断的long int类型的数字)。在这种情况下,您必须显式使用LL后缀来启用long long扩展(在大多数编译器上)。

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


1

您的代码在这里可以正常编译(即使未注释该行。也必须将其更改为

num3 = 100000000000000000000;

开始收到警告。


什么编译器?在C ++中,整数文字是int或适合它的long中的较小者。在C99中,它是int,long和long long中的最小值。因此,当长期将C ++作为非标准扩展使用时,也许您的编译器也对文字采用了C99规则。
史蒂夫·杰索普

在64位linux系统上的gcc版本4.3.2(Debian 4.3.2-1.1)。
Omry Yadan

@SteveJessop也许有点晚:但是长不一定是64位。大多数时候都是这样,但您无法保证它无处不在。您拥有的唯一保证是,它至少与int一样大,而int至少与short int一样大,而short int至少与char一样大。最后,将char定义为足以表示实现的基本字符集中的每个字符(通常为8位)的字符。
pauluss86

@ pauluss86:我不是在说担保。Omry说他在64位Debian系统上使用gcc 4.3.2。我观察到,这解释了他所看到的情况,因为(在一般情况下,我偶然知道)gcc在此类系统上默认配置为使用long与该操作系统的LP64 ABI一致的64位。
史蒂夫·杰索普

@SteveJessop我并不是说您的评论是错误的!仅指出,很长的假设是到处都是64位,这很不幸,很多人认为这是危险的。
pauluss86
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.