简体   繁体   中英

Literals types in VC++

I know the standard is as follows:

  • Integrals starting with 0 are interpreted as octal.
  • Integrals starting with 0x or 0X are interpreted as hexadecimal.

The type of an integer literal depend on its value and notation:

  • Decimals are by default signed and has the smallest type of int, long, long long in which the value fits.
  • Hexadecimal and octal can be signed or unsigned and have the smallest type of int, unsigned int, long, unsigned long, long long, unsigned long long in which the literal value fits.
  • No literals of type short but this can be override by a suffix.

But what about VC++?! It seems to be treating decimal, octal and hexadecimal the same and unsigned types are also allowed for decimals.

something like the following code:

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

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

gives:

unsigned long
__int64
unsigned int
__int64

Is this expected and why it is different from the standard?

It appears that as far as your first result goes, VC++ still follows the rule from C89/90, which said (§ 6.1.3.2):

The type of an integer constant is the first of the corresponding list in which its value can be represented. Unsuffixed decimal: int , long int , unsigned long int ; [...]

So, since 4294967295 can be represented as an unsigned long int , that's what it's using.

In C++98/03, this is still permitted, but no longer required -- you're using a value larger than can be represented in an long int , which gives undefined behavior (§ 2.13.1/2):

If it is decimal and has no suffix, it has the first of these types in which its value can be represented: int , long int ; if the value cannot be represented as a long int, the behavior is undefined.

[emphasis added]

C++11 adds long long int to the list, so that's the type 4294967295 should become, but even in VC++ 2013 RC, it still follows the C89/90 standard in this respect and gives it type unsigned long int .

Note that the the string produced by typeid is implementation defined, so it doesn't have to correspond directly to the proper name of the type. If you use overloading, we can see that 0x100000000 and 4294967296 have type long long though:

#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);
}

Result with VC++ 2008 and VC++ 2013 RC:

unsigned long
long long
unsigned int
long long

I don't have all the intervening versions installed, but given that 2008 and 2013 match, I think it's fair to guess that versions in between them act the same way as well.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM