4

私は標準が次のとおりであることを知っています:

  • 0 で始まる整数は 8 進数として解釈されます。
  • 0x または 0X で始まる整数は、16 進数として解釈されます。

整数リテラルの型は、その値と表記法によって異なります。

  • 10 進数はデフォルトで符号付きで、値が収まる最小の型の int、long、long long を持ちます。
  • 16 進数と 8 進数は、signed または unsigned にすることができ、リテラル値が収まる最小の型の int、unsigned int、long、unsigned long、long long、unsigned long long を持ちます。
  • short 型のリテラルはありませんが、これは接尾辞でオーバーライドできます。

しかし、VC++ はどうですか?! 10進数、8進数、16進数を同じように扱っているようで、10進数には符号なしの型も許可されています。

次のコードのようなもの:

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

これは予想されることであり、標準と異なる理由は何ですか?

4

1 に答える 1

6

最初の結果に関する限り、VC++ は引き続き C89/90 のルールに従っているようです (§ 6.1.3.2):

整数定数の型は、その値を表すことができる対応するリストの最初のものです。接尾辞なしの 10 進数: int, long int, unsigned long int; [...]

したがって、 4294967295 は として表すことができるためunsigned long int、それが使用されています。

C++98/03 では、これは引き続き許可されていますが、必須ではなくなりました。 で表現できる値よりも大きな値を使用しているためlong int、未定義の動作が発生します (§ 2.13.1/2):

10 進数で接尾辞がない場合は、値を表すことができる次の型の最初のものを持ちintますlong int値を long int として表すことができない場合、動作は未定義です。

【強調追加】

C++11 がlong long intリストに追加されたので、その型になる4294967295 はずですが、VC++ 2013 RC でも、この点で C89/90 標準に従っており、 type を与えていunsigned long intます。

によって生成される文字列typeidは実装定義であるため、型の適切な名前に直接対応する必要はないことに注意してください。オーバーロードを使用すると、それがわかり、型0x100000000を持つことができます。4294967296long 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 が一致していることを考えると、それらの間のバージョンも同じように動作すると推測するのが妥当だと思います。

于 2013-10-03T19:45:30.280 に答える