VC++中的字面量类型

4

我知道的标准如下:

  • 以 0 开头的整数被解释为八进制。
  • 以 0x 或 0X 开头的整数被解释为十六进制。

整数字面值的类型取决于其值和表示法:

  • 十进制默认为有符号整型,类型为 int、long、long long 中最小的适合该值的类型。
  • 十六进制和八进制可以是有符号或无符号的,并且类型为 int、unsigned int、long、unsigned long、long long、unsigned long long 中最小的适合该字面值的类型。
  • 没有类型为 short 的字面值,但这可以通过后缀进行覆盖。

但 VC++ 如何处理呢?!它似乎将十进制、八进制和十六进制视为相同,并且对于十进制也允许无符号类型。

像下面的代码一样:

cout << typeid(4294967295).name() << endl;
cout << typeid(4294967296).name() << endl;

cout << typeid(0xffffffff).name() << endl;
cout << typeid(0x100000000).name() << endl;

提供:

unsigned long
__int64
unsigned int
__int64

这是否是预期的,为什么与标准不同?

1
你认为这与标准有什么不同? - John Dibling
2
在C++11中,4294967295应该适用于long long类型,因此它永远不可能具有无符号类型。然而,在C++11之前,unsigned long是一个有效的结果。 - user743382
2
@GManNickG 这取决于[lex.icon]在C++标准中的定义。 - user743382
1
@hvd,JerryCoffin:什么...今天我学到了一些东西。 - GManNickG
1
@Red 这在C++11中发生了变化,因为C++11引入了long long。在此之前,最大的标准整数类型是long/unsigned long,通常只有32位。 - user743382
显示剩余6条评论
1个回答

6
似乎就你的第一个结果而言,VC++仍然遵循C89/90的规则(§6.1.3.2),该规则规定:
整数常量的类型是对应列表中第一个可以表示其值的类型。无后缀十进制:int、long int、unsigned long int;[...]
因此,由于4294967295可以表示为unsigned long int,所以它正在使用这个类型。
在C++98/03中,这仍然是允许的,但不再是必需的——您正在使用一个比long int还大的值,这会导致未定义的行为(§2.13.1/2):
如果它是十进制的且没有后缀,则它具有以下类型中的第一个类型,其中它的值可以被表示:int、long int;如果该值无法表示为long int,则行为是未定义的。
[强调添加]
C++11将long long int添加到列表中,因此4294967295应该成为这种类型,但即使在VC++ 2013 RC中,它仍然遵循C89/90标准,在这方面给出了unsigned long int类型。
请注意,typeid生成的字符串是实现定义的,因此它不必直接对应于类型的正确名称。如果使用重载,我们可以看到0x100000000和4294967296具有long long类型:
#include <iostream>

void f(unsigned long){
    std::cout << "unsigned long\n";
}

void f(long long) {
    std::cout << "long long\n";
}

void f(unsigned long long) {
    std::cout << "unsigned long long\n";
}

void f(unsigned) {
    std::cout << "unsigned int\n";
}

int main(){
    f(4294967295);
    f(4294967296);
    f(0xffffffff);
    f(0x100000000);
}

使用VC++ 2008和VC++ 2013 RC的结果:

unsigned long
long long
unsigned int
long long

我没有安装所有中间版本,但考虑到2008和2013匹配,我认为可以猜测它们之间的其他版本也会以同样的方式运行。


它是如何产生 __int64 的?它没有遵循 C99 吗? - John Dibling
1
@JohnDibling: typeid产生的字符串是实现定义的。类型实际上是long long。 - Jerry Coffin
好的,但是long long不在C90的列表中。我猜这里的底线是,在VC10中这是未定义行为? - John Dibling
@hvd:抱歉——通常情况下,我将C++98和03视为同义词,除非另有说明,但我已经进行了编辑以使其更完整。 - Jerry Coffin
感谢您详细的回答。今天我学到了许多新东西 :) - Red
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接