Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Constant integer promotion rules?

Tags:

c++

c++11

To give a little background (unrelated to the question, which will follow), in C++11 I noticed a narrowing issue:

int foo[] = { 0xFFFFFFFF };

This was failing to compile (narrowing conversion) because 0xFFFFFFFF is an unsigned int. However, I've seen cases where 0xFF is signed.

I've looked over integer promotion rules, but this is mostly within the context of lvalues and not rvalues/constants. How does the compiler determine the type of constants (without literal suffixes)? Is there documentation or a nice little table / "cheat sheet" that shows the rules for this? I'm not even really sure what this is called, otherwise I'd have attempted to find it myself in the C++11 standard.

Thanks in advance.

like image 743
void.pointer Avatar asked Sep 02 '14 21:09

void.pointer


3 Answers

There's a table in the standard, which is reproduced on cppreference.com: http://en.cppreference.com/w/cpp/language/integer_literal

In particular, a hex or octal integer literal with no suffix is considered to have the first type in the following list in which its value can be represented:

int
unsigned int
long int
unsigned long int
long long int
unsigned long long int

0xFFFFFFFF is too big for int if int is 32 bits long, so unsigned int is chosen. But 0xFF fits comfortably into an int, so int it is.

like image 150
Brian Bi Avatar answered Oct 11 '22 14:10

Brian Bi


What are called referred to as Integer constants in C are referred to as integer literals in C++. The rules used to determine the type of an integer literal are covered in the draft C++ standard section 2.14.2 Integer literals table 6 which says:

The type of an integer literal is the first of the corresponding list in Table 6 in which its value can be represented.

and for Octal or hexadecimal constant with no suffix the table has the following order:

int
unsigned int
long int
unsigned long int
long long int
unsigned long long int

So 0xFF can be represented as an int while the first type that can represent 0xFFFFFFFF would be unsigned int.

The order for Decimal Constants is as follows:

int
long int
long long int

As we can see hexidecimal and octal literals behave differently, and we can see that C99 has the same table. The Rationale for International Standard—Programming Languages—C says the following about this:

Unlike decimal constants, octal and hexadecimal constants too large to be ints are typed as unsigned int if within range of that type, since it is more likely that they represent bit patterns or masks, which are generally best treated as unsigned, rather than “real” numbers.

cppreference integer literal section also quotes table 6 in the The type of the literal sub-section.

like image 26
Shafik Yaghmour Avatar answered Oct 11 '22 14:10

Shafik Yaghmour


0xFF is never negative. It is an alternative way of writing 255. (It has type int).

0xFFFFFFFF is a large positive number. There is a table under [lex.icon] that specifies what the type is of an integer constant. For hex constants with no suffix, it is the first type in the following list that can hold that large positive number: int, unsigned int, long int, unsigned long int, long long int, unsigned long long int. The implementation might add custom types ot this list.

like image 38
M.M Avatar answered Oct 11 '22 15:10

M.M