【问题标题】:Literals types in VC++VC++ 中的文字类型
【发布时间】:2013-10-03 19:05:10
【问题描述】:

我知道标准如下:

  • 以 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

这是预期的吗?为什么它与标准不同?

【问题讨论】:

  • 您认为这与标准有何不同?
  • 在 C++11 中,4294967295 应该适合 long long 类型,因此它永远不能有无符号类型。但是,在 C++11 之前,unsigned long 是一个有效的结果。
  • 哪个版本的 VC++,顺便说一句?
  • @GManNickG 确实取决于此,请查看 C++ 标准中的 [lex.icon]。
  • @GManNickG:实际上他是对的(参见第 2.14.2 节,表 6)。

标签: c++ visual-c++ c++11


【解决方案1】:

看来,就您的第一个结果而言,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吗?
  • @JohnDibling: typeid 产生的字符串是实现定义的。类型真的很长很长。
  • 好的,但 long long 不在 C90 的列表中。我想这里的底线是在 VC10 中这是 UB?
  • 我有VC10,类型匹配。
  • “在 C++03 中,这仍然是允许的,但不再需要”有点误导:这条 C90 规则是从 C++ 标准的第一个版本 C 中删除的++98.
猜你喜欢
  • 1970-01-01
  • 2011-10-17
  • 1970-01-01
  • 2019-08-18
  • 2011-02-10
  • 2016-12-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多