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

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.

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.

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)

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.

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.

Related

Why does the base of a literal affect its type?

The decimal number 4294967295 is equal to hexadecimal 0xFFFFFFFF, so I would expect a literal to have the same type regardless of what base it is expressed in, yet
std::is_same<decltype(0xFFFFFFFF), decltype(4294967295)>::value; //evaluates false
It appears that on my compiler decltype(0xFFFFFFFF) is unsigned int, while decltype(4294967295) is signed long.
hex literals and decimal literals types are determined differently from lex.icon table 7
The type of an integer literal is the first of the corresponding list in Table 7 in which its value can be represented.
when there is no suffix for decimal literal the types listed are in order:
integer
long int
long long int
for hexidecimal the list in order are:
int
unsigned int
long int
unsigned long int
long long int
unsigned long long int
Why does this difference exist? Considering we also have this in C, we can look at the C99 rationale document and it says:
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.

what does L represent in "<any hex number>L"

I am looking through some c++ code and I came across this:
if( (size & 0x03L) != 0 )
throw MalformedBundleException( "bundle size must be multiple of four" );
what does L stand for after the hexadecimal value ?
how does it alter the value 0x03 ?
It means Long, as in, the type of the literal 0x03L is long instead of the default int. On some platforms that will mean 64 bits instead of 32 bits, but that's entirely platform-dependent (the only guarantee is that long is not shorter than int).
This suffix sets the type of the numeric literal. L stands for long; LL stands for long long type. The number does not need to be hex - it works on decimals and octals as well.
3LL // A decimal constant 3 of type long long
03L // An octal constant 3 of type long
0x3L // A hex constant 3 of type long
It means so-called long-suffix of integer literals and denotes that the type of the literal is int long The integer literal in your example is hexadecomal integer literal of type int long.
You can meet also two LL (or ll) that denote type int long long

ULL suffix on a numeric literal

I've run across some code like this:
line += addr & 0x3fULL;
Obviously, 'U' and 'L' are not hex digits. I'm guessing that the 'ULL' at the end of that hex numeric literal means "Unsigned Long Long" - am I correct? (this sort of thing is very difficult to google) if so then this is some sort of suffix modifier on the number?
From the gcc manual:
ISO C99 supports data types for integers that are at least 64 bits wide ( . . . ) . To make an integer constant of type long long int, add the suffix LL to the integer. To make an integer constant of type unsigned long long int, add the suffix ULL to the integer.
These suffixes have also been added to C++ in C++11, and were already supported long long (pun intended) before that as compiler extensions.
Yes that's correct.
0x prefix makes it a hexadecimal literal.
ULL suffix makes it type unsigned long long.
I'm positing a new answer because I recognize that the current answers do not cite from a cross platform source. The c++11 standard dictates that a literal with U/u and LL/ll suffixes is a literal of type: unsigned long long int [source]
U/u is the C/C++ suffix for an unsigned integer.
LL/ll is the C/C++ suffix for a long long integer which is a new type in C++11 and required to have a length of at least 64-bits.
Notes:
The keyword int may be omitted if any modifiers are used, unsigned long long for example. So this will define one as an unsigned long long int, and any number assigned to it will be static_cast to unsigned long long int: unsigned long long one = 1
c++11 marked the advent of auto. Which sets the variable type to the type assigned to it on declaration. For example, because 2ULL is an unsigned long long int literal two will be defined as an unsigned long long int: auto two = 2ULL
c++14 introduced order independent literal suffixes. Previously the U/u suffix had to preceded any size suffix. But circa c++14 the suffixes are accepted in either order, so now since 3LLU is an unsigned long long int literal three will be defined as an unsigned long long int: auto three = 3LLU

Static unsigned int foo and later if ( foo >0 )?

The book told that writing:
static unsigned int foo;
and later
if( foo > 0)
{
is wrong, and it will leads to a hard to find bug.
Why is that?
In the x86 assembly language programming there are signed arithmetic instructions and
also unsigned arithmetic instructions,
JG JL <-signed arithmetic
JB JA <- unsigned instructions.
So the compiler can just assemble that if (foo >0 ) statement with unsigned instructions
isn't it? Can somebody explain how it works in advance?
Is that instruction wrong? Or if there is a difference in "C" where "C++" is strict in
that case? Please explain.
Here we are comparing a unsigned variable with a immediate value. What is happening inside
the compiler actually in this case?
And when we compare a signed value with unsigned value what happens? Then what instructions will compiler choose, signed instructions or unsigned instructions?
--thanks in advance--
This question should not be answered on the level of assembler but stil on c/c++ language level. On most architectures it is impossible to compare signed and unsigned numbers, and c/c++ does not facilitate such comparisons. Instead there are rules about converting one of the operands to type of the other in order to compare them - see for example aswers to this question
About comparing to literals - typical way of doing it (as you did) is not wrong, but you can do it better - according to c++ standard:
2.13.1.1 An integer literal is a sequence of digits that has no period
or exponent part. An integer literal may have a prefix that specifies
its base and a suffix that specifies its type. The lexically first
digit of the sequence of digits is the most significant. A decimal
integer literal (base ten) begins with a digit other than 0 and con-
sists of a sequence of decimal digits. An octal integer literal (base
eight) begins with the digit 0 and con- sists of a sequence of octal
digits.22) A hexadecimal integer literal (base sixteen) begins with 0x
or 0X and consists of a sequence of hexadecimal digits, which include
the decimal digits and the letters a through f and A through F with
decimal values ten through fifteen. [Example: the number twelve can be
written 12, 014, or 0XC. ]
2.13.1.2 The type of an integer literal depends on its form, value,
and suffix. 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 repre- sented as a long int, the behavior is
undefined. If it is octal or hexadecimal and has no suffix, it has the first of these types in which its value can be represented: int,
unsigned int, long int, unsigned long int. If it is suffixed by u or
U, its type is the first of these types in which its value can be
repre- sented: unsigned int, unsigned long int. If it is suffixed by l
or L, its type is the first of these types in which its value can be
represented: long int, unsigned long int. If it is suffixed by ul, lu,
uL, Lu, Ul, lU, UL, or LU, its type is unsigned long int.
If you want to be sure about your literal type (and therefore comaprison type) add described suffixes to ensure right type of literal.
It is also worth noticing that literal 0 is actually not decimal but octal - it doesn't seem to change anything, but is quite unexpected - or am I wrong?
To summarize - it is not wrong to write code like that, but you should remeber that in certain conditions in might behave counter-intuitive (or at least counter-mathematical ;)

Unsigned keyword in C++

Does the unsigned keyword default to a specific data type in C++? I am trying to write a function for a class for the prototype:
unsigned Rotate(unsigned object, int count)
But I don't really get what unsigned means. Shouldn't it be like unsigned int or something?
From the link above:
Several of these types can be modified using the keywords signed, unsigned, short, and long. When one of these type modifiers is used by itself, a data type of int is assumed
This means that you can assume the author is using ints.
Integer Types:
short -> signed short
signed short
unsigned short
int -> signed int
signed int
unsigned int
signed -> signed int
unsigned -> unsigned int
long -> signed long
signed long
unsigned long
Be careful of char:
char (is signed or unsigned depending on the implmentation)
signed char
unsigned char
Does the unsigned keyword default to a data type in C++
Yes,signed and unsigned may also be used as standalone type specifiers
The integer data types char, short, long and int can be either signed or unsigned depending on the range of numbers needed to be represented. Signed types can represent both positive and negative values, whereas unsigned types can only represent positive values (and zero).
An unsigned integer containing n bits can have a value between 0 and 2n - 1
(which is 2n different values).
However,signed and unsigned may also be used as standalone type specifiers, meaning the same as signed int and unsigned int respectively. The following two declarations are equivalent:
unsigned NextYear;
unsigned int NextYear;
You can read about the keyword unsigned in the C++ Reference.
There are two different types in this matter, signed and un-signed. The default for integers is signed which means that they can have negative values.
On a 32-bit system an integer is 32 Bit which means it can contain a value of ~4 billion.
And when it is signed, this means you need to split it, leaving -2 billion to +2 billion.
When it is unsigned however the value cannot contain any negative numbers, so for integers this would mean 0 to +4 billion.
There is a bit more informationa bout this on Wikipedia.
Yes, it means unsigned int. It used to be that if you didn't specify a data type in C there were many places where it just assumed int. This was try, for example, of function return types.
This wart has mostly been eradicated, but you are encountering its last vestiges here. IMHO, the code should be fixed to say unsigned int to avoid just the sort of confusion you are experiencing.