Captain McDonalds
Captain McDonalds

Reputation: 45

C++ Primer paragraph on Integer literals, need someone to clarify some points

I'm currently working through C++ Primer (5th Edition), and I'm struggling trying to figure out what the author means in this part on literals (Chapter 2, section 2.1.3):

... By default, decimal literals are signed whereas octal and hexadecimal literals can be either signed or unsigned types. A decimal literal has the smallest type of int, long, or long long (i.e., the first type in this list) in which the literal’s value fits. Octal and hexadecimal literals have the smallest type of int, unsigned int, long, unsigned long, long long, or unsigned long long in which the literal’s value fits. It is an error to use a literal that is too large to fit in the largest related type...

In the first sentence, does the author mean that decimal literals are signed according to the C++ standard, and for octal and hexadecimal literals it depends on the compiler?

The next three sentences really confuse me though, so if someone could offer an alternative explaination, it would be greatly appreciated.

Upvotes: 2

Views: 260

Answers (4)

Chris Dodd
Chris Dodd

Reputation: 126536

The place this is relevant is when you have literal values that are just a little too big to fit in a signed type, but do fit in the corresponding unsigned type. For example, on a machine with 16-bit int and 32-bit long (rare these days, but the minimum allowed by the spec), the constant literal 0xffff will be an unsigned int, while the literal 65535 (same value) will be a long.

Of course, you can force the latter to be an unsigned by using a U suffix; this part of the spec is only relevant for literals with no suffix.

Upvotes: 1

Vlad from Moscow
Vlad from Moscow

Reputation: 311146

If you have an integer literal for example a decimal integer literal the compiler has to define its type. For example a decimal literal can be used in expressions and the compiler need to determine the type of an expression based on the types of its operands.

So for decimal integer literals the compiler selects between the following types

int
long int
long long int

and choices the first type that can accomodate the decimal literal.

It does not consider unsigned integer types as for example unsigned int or unsigned long int though they could accomodate a given literal.

The situation is different when the compiler deals with octal or hexadecimal integer literals. In this case it considers the following types in the given order

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

That it would be more clear consider an artificial example to demonstrate the idea. Let's assume that you have a value equal to 127. This value can be stored in type signed char. Now what about value 128? It can not be stored in an object of type signed char because the maximum positive value that can be stored in an object of type signed char is 127.

What to do? We could store 128 in an object of type unsigned char because its maximum value is 255. However the compiler prefers to store it in an object of type signed short.

But if this value was specified like 0x80 then the compiler would select an object of type unsigned char

It is of course an imaginary process.

However in realty a similar algorithm is used for decimal literals only the compiler takes into account integer types starting from int that to determine the type of a decimal literal.

Upvotes: 3

Captain Giraffe
Captain Giraffe

Reputation: 14705

To append to Cory's answer:

The relevant diagram in the link states

Types allowed for integer literals

No suffix, regular decimal

int, long int, long long int(since C++11)

So the decimal number

78625723

Is represented by a signed type.

No suffix hexadecimal or octal bases

int, long int, 
unsigned int, unsigned long int
long long int(since C++11)
unsigned long long int(since C++11) 

So the 0x hex number

0x78625723

Might be represented by a signed or an unsigned value.

Upvotes: 1

Cory Kramer
Cory Kramer

Reputation: 118021

Decimal (meaning base-10) literals are those that have no prefix. The author is saying that these are always signed.

5      // signed int (decimal)
12     // signed int (decimal)

They can also be signed or unsigned based on either you providing a suffix. Here's a full reference for integer literal syntax.

5      // signed int
7U     // unsigned int
7UL    // unsigned long

Hex (base-8) values will be prefixed with 0x.

0x05   // int (hex)

Similarly octal (base-8) values are prefixed with 0.

05     // int (octal)

Upvotes: 3

Related Questions