【问题标题】:C++ literal integer typeC++ 文字整数类型
【发布时间】:2017-03-19 21:03:00
【问题描述】:

文字表达式也有类型吗?

long long int a = 2147483647+1 ;
long long int b = 2147483648+1 ; 
std::cout << a << ',' << b ; // -2147483648,2147483649

【问题讨论】:

  • 因为你先做a+1 然后把它转换成long long。
  • 检查一下,你的疑虑就会一扫而光:stackoverflow.com/questions/1819189/…
  • 我看不出关于 long long 的问题与“文字表达式也有类型吗?”的问题有什么关系。
  • long long in C/C++的可能重复
  • 答案是“是”,而 2147483647 的类型要么是 int,要么是(最多)long。我知道当前没有添加一个不会溢出的实现。

标签: c++ int long-integer integer-overflow


【解决方案1】:

是的,文字数字有类型。无后缀十进制整数文字的类型是可以表示整数的intlonglong long 中的第一个。二进制、十六进制和八进制文字的类型选择类似,但列表中也包含无符号类型。

您可以通过使用U 后缀来强制使用无符号类型。如果您在后缀中使用单个L,则类型至少为long,但如果不能表示为long,则可能为long long。如果你使用LL,那么类型必须是long long(除非实现的扩展类型比long long更宽)。

结果是,如果 int 是 32 位类型,long 是 64 位,那么 2147483647 的类型为 int,而 2147483648 的类型为 long。这意味着2147483647+1 将溢出(这是未定义的行为),而2147483648+1 只是2147483649L

这是由 C++ 标准的 §2.3.12 ([lex.icon]) 第 2 段定义的,上述描述是该部分中表 7 的摘要。

请务必记住,赋值目标的类型不会以任何方式影响赋值右侧表达式的值。如果你想强制计算得到 long long 结果,你需要强制计算的一些参数是 long long;仅分配给 long long 变量是不够的:

long long a = 2147483647 + 1LL;
std::cout << a << '\n';

产生

2147483648

(live on coliru)

【讨论】:

  • 是否有义务使用可以表示的最小整数类型?你能提供一个引用吗?
  • @m7913d:是的,标准准确地说是“对应列表中的第一个”。我添加了引用。 (它不是可以表示的最小整数类型;永远不会是charshort。)
  • @rici:值得注意的是文字字符,例如 'a' 将是 char 类型(与 C 不同,它将是 int 类型)。
  • @rodrigo,是的,带小数点的文字将属于 double 类型:) 字符文字位于标准的不同部分,具有大量不同类型(例如, u'a' 的类型为 char16_t)。我认为这些复杂性并没有真正增加这个问题的任何内容,但你可以不同意。
  • 除了以上所有,注意微软编译器使用32位int和32位long,所以2147483648的类型为long long,2147483647L+1也会溢出。
【解决方案2】:
int a = INT_MAX ;
long long int b = a + 1 ; // adds 1 to a and convert it then to long long ing
long long int c = a; ++c; // convert a to long long int and increment the result with 1
cout << a << std::endl; // 2147483647
cout << b << std::endl; // -2147483648
cout << c << std::endl; // 2147483648
cout << 2147483647 + 1 << std::endl; // -2147483648 (by default integer literal is assumed to be int)
cout << 2147483647LL + 1 << std::endl; // 2147483648 (force the the integer literal to be interpreted as a long long int)

您可以找到有关整数文字 here 的更多信息。

【讨论】:

  • 2147483647 可能是 int 类型,但也可能是 long 类型。此外,2147483647 + 1 很可能是整数溢出,这不是-2147483648,而是未定义的行为。最后 2147483647L + 1 可以溢出(微软编译器也会溢出)。
  • @MartinBonner 我将答案更改为使用 long long,这在 Windows 上也是 64 位。请注意,尽管根据 c++ 标准它是未定义的行为,但它几乎总是作为 2 补码溢出实现,这是 OP 注意到的行为。
  • @MartinBonner 根据 rici 的回答,它应该是一个 int(如果你假设 int 是 32 位)
  • @m7913d:我认为 Martin 的观点是 int 有可能是 16 位,而 long 必须至少是 32 位。对于 16 位 int 和 32 位 long,文字 2147483647 的类型为 long(但添加一个仍然是溢出)。
  • 值得知道整数溢出通常表现为二补码(用于调试和预测有缺陷的程序如何进入它所做的状态,但也值得指出它是未定义的行为并且 任何事情都可能发生。参见gcc.gnu.org/bugzilla/show_bug.cgi?id=33498,因为整数溢出,GCC 将一个从 0 计数到 63 的完全普通的循环变成了无限循环
猜你喜欢
  • 2015-04-17
  • 1970-01-01
  • 1970-01-01
  • 2015-06-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多