Numeric Literals - Embedded.com

# Numeric Literals

### Numeric Literals

Dan Saks

Every literal has a type.It may not be obvious, and it may vary across platforms,but the standard does specify it precisely.

The C language provides severaldifferent kinds of constants: integerconstants such as `10` and `0x1C` , floatingconstants such as `1.0` and `6.022e+23` ,and character constants such as `'a'` and `'x10'` . C also provides string literals such as `"ouch!"` and `"n"` . C++ providesthe same kinds of constants andliterals, except the C++ standard justcalls all of them literals instead. I do,too.

Every literal in C and C++ has atype. For example, `10` is obviously aninteger. But is it an `int` (which is`signed` by default) an `unsigned int` , or a `short` or `long` variationthereof? Do you even care?If you're a C programmer, youmight not care. Part of me hopesyou'd care, but I'm not absolutelysure you need to. Many C programmersapparently get by quite wellwithout knowing the exact types ofconstants.

If you're a C++ programmer, youreally should care. C++ supportsfunction name overloading, and theexact type of a literal just mightdetermine which function is the bestmatch for a particular call. Forexample, given:

int f(int);
unsigned int f(unsigned int);
long int f(long int);

which of these functions does `f(10)` call? The answer is:

int f(int);

because the precise type of `10` is `(signed)int` .

Forms of integer literals
An integer literal takes differentforms:

• A decimal integer literal (base 10) is a non-zero digit followed by zero or more decimal digits
• A hexadecimal integer literal (base sixteen) is `0x` or `0X` followed by a sequence of one or more hexadecimal digits
• An octal integer literal (base eight) is the digit `0` followed by a sequence of zero or more octal digits

For example, the decimal integer literal`63` can also be expressed as the hexadecimalinteger literal `0x3F` or as theoctal integer literal `077` .

Any integer literal may have a suffixthat influences its type:

`U` or `u` specifies that the literal has an `unsigned` type`L` or `l` specifies that the literal has a `long` type`LL` or `ll` specifies that the literal has a `long long` type. (This is available in the most recent edition of Standard C, C99, but not in earlier versions of C or in C++)

For example, `63u` has type `unsignedint` . `0x3FL` has type `(signed)long int` .An integer literal suffix may combine`U` with either `L` or `LL` (in either upperor lower case and in either order), sothat both `63ul` and `0x3FLU` have type`unsigned long int` .

An integer literal's suffix influencesthe literal's type, but does not determineit. The type also depends on theliteral's value.

Types of integer literals
In general, an integer literal's type isthe smallest integer type no smallerthan int that can hold the literal'svalue and still satisfy the constraintsimposed by the form and suffix. Forexample, the type of a decimal integerliteral with no suffix is the smallest(the first) of the following types thatcan represent its value: `int` , `long int` ,and in C99, `long long int` . Becausethe maximum values of the types varyacross platforms, the exact types formany integer literals also vary acrossplatforms.

Both the C and C++ standards allowconsiderable slack in the range of valuesfor integer types. The maximumvalue for an `int` must be at least215 -1, and the maximum value for a`long int` must be at least 231 -1. Inpractice, this means that an `int` mustoccupy at least 16 bits and a `longint` must occupy at least 32 bits.

On any platform, `int` and `long int` may occupy more than their minimumstorage requirement, as long as a `long int` occupies at least as much storage asan `int` . An unsigned integer type mustoccupy the same amount of storage as itscorresponding signed integer type. Forinstance, a 16-bit platform might use 16bits for `int` and `unsigned int` and 32bits for `long int` and `unsigned long int` . A 32-bit platform might use 32 bitsfor all four types, `int` , `unsigned int` ,`long int` , and `unsigned long int` .

Table 1 describes the rules for determiningthe type of an integer literal inC99 and C++. A literal whose value can'tbe represented in any of the listed typesproduces a compile error.

Click on image to enlarge.

The rules in Table 1 lead to somepotential portability problems. A decimalinteger literal whose value is notgreater than 32,767 (= 215 -1) has typeint on every standard C and C++ environment.No surprise there. However,any decimal integer literal whose value isgreater than 215 -1 but not greater than231 -1 has type long int on a 16-bit platform,but just plain int on a 32-bit platform.

`int f(int);unsigned int f(unsigned int);long int f(long int);unsigned long int	f(unsigned long int);`

calling `f(32768)` calls `f(long int)` when compiled using C++ for a 16-bitplatform, but it calls `f(int)` when compiledfor a 32-bit platform. On the otherhand, if you write the call as `f(0x8000)` (`0x8000` is 32,768 as a hexadecimal literal),it calls `f(unsigned int)` on everyplatform.

Floating literals
Floating literals offer a few little surprises,too. The type of a floating literal suchas `1.0` or `6.022e+23` is `double` , not`float` . Appending the letter `F` or `f` toa floating literal makes its type `float` .Appending the letter L or l to a floatingliteral makes its type long double . Forexample, 1.0F has type float , and6.022e+23L has type long double .Combining F and L (in either case andin either order) in a floating literal is asyntax error.

In C++, the only form of a floating literalis a decimal floating literal, in whichall of the digits (in both the significantpart and the exponent part) are decimaldigits. C99 also provides hexadecimalfloating literals, in which the digits of thesignificant part are hexadecimal digits.

In a decimal floating literal, theexponent part is optional. If present, itbegins with `E` or `e` followed by decimaldigits representing a power of 10. In ahexadecimal floating literal, the exponentpart is mandatory. Since `E` and `e` are valid hexadecimal digits, a hexadecimalfloating literal uses `P` or `p` to markthe beginning of the exponent part, followingby decimal digits representing apower of two. For example,`0x1.FFFFFEp127f` is a floating constantwhose value is `0x1.FFFFFE` multiplied by2127 (decimal). The `f` at the end of theliteral specifies that the literal's type is `float` .

Neither the form nor value of afloating literal affects its type. The suffixletter (or absence thereof) completelydetermines the type.

Character and string literals
Integer and floating literals are essentiallythe same in both C and C++. The differenceslie in C's added support for`long long` integer types and hexadecimalfloating literals. In contrast, characterand string literals behave slightly differentlybetween C and C++. Those differencesare my topic for next time.

Dan Saks is the president of Saks &Associates, a C/C++ training and consultingcompany. He is also a consulting editor for theC/C++ Users Journal. He served for manyyears as secretary of the C++ standards committee.With Thomas Plum, he wrote C++Programming Guidelines (Plum Hall).

This site uses Akismet to reduce spam. Learn how your comment data is processed.