2013-10-03 15 views
4

我知道的標準如下:字面類型在VC

  • 積分從0開始被解釋爲八進制。
  • 以0x或0X開頭的積分被解釋爲十六進制。

類型字面整數取決於它的價值和符號:

  • 小數默認情況下籤署,並具有最小的類型爲int,長,很長很長的,它的值相符。
  • 十六進制和八進制可以是有符號或無符號的,並且具有最小類型的int,unsigned int,long,unsigned long,long long,unsigned long long,其中文字值適合。
  • 沒有短文字的文字,但可以用後綴覆蓋。

但是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

您認爲這與標準有什麼不同? –

+2

在C++ 11中,4294967295應該適合long long類型,所以它永遠不會有無符號類型。但是,unsigned long是C++ 11之前的有效結果。 – hvd

+1

哪個版本的VC++,BTW? – Angew

回答

6

似乎只要你的第一個結果去,VC++仍然遵循從C89/90,其中,所述規則(第6.1.3.2):

類型的整數常數的是第可以表示其值的相應列表。非隨意十進制:intlong int,unsigned long int; [...]

因此,由於4294967295可以表示爲unsigned long int,這就是它所使用的。在C++ 98/03中,這仍然是允許的,但不再需要 - 您使用的值大於可在long int中表示的值,這會給出未定義的行爲(§2.13.1/2) :

如果是小數並且沒有後綴,它具有第一這些類型的,其中它的值可被表示的:intlong int; 如果該值不能表示爲long int,則行爲是未定義的。

[強調]

C++ 11增加long long int到列表中,所以這類型4294967295應該成,但即使是在VC++ 2013 RC,它依然沿用了C89/90標準在這方面,並給它類型unsigned long int

請注意,由typeid生成的字符串是實現定義的,因此它不必直接對應於類型的正確名稱。如果你使用重載,我們可以看到,0x1000000004294967296有型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年的比賽,我認爲可以推測他們之間的版本同樣如此。

+0

那麼它是如何產生'__int64'呢?它不遵循C99嗎? –

+1

@JohnDibling:由typeid生成的字符串是實現定義的。這種類型真的很長。 –

+0

好的,但'long long'不在C90的列表中。我猜這裏的底線是在VC10中這是UB? –