In the C language expressions are typed inside-out: literals have types. E.g. 123
is an int, and 123U
is an unsigned int, 123L
is a long int and so on. The type of an expression depends on the types of the subexpressions: the type of a + b
depends on the types of a
and b
.
Ensuring the correct type is particularly important when doing bit-fiddling. You also have to take care for large literals that do not fit into an int (or the type of a variable you are assigning the expression value to – narrowing conversions are a common source of bugs).
However, most code should not explicitly use a long
type or the L
literal suffix because the size of long integers is platform dependent. Integers and long integers may even have the same size.
For portable code that needs a specific size, it is more correct to use the C99 fixed width integer types (like int64_t
). They do not have corresponding literal suffixes, instead you have to use the literal macros like INT64_C(123)
from stdint.h
. These macros will apply the correct casts or platform-dependent type suffixes if necessary.
In C++ the type of an expression may affect with overloads are invoked. Notably 0
, '\0'
, false
and nullptr
often behave very differently, despite all being “null” and to some degree being implicitly convertible to each other.
long fileSize = 12345L;
In many languages the default, unadorned number is assumed to be anint
. Many languages hide that fact by providing implicit up-converts. Still some languages don't and you have to be specific. What really makes a suffix required is when the default type is larger than what you need. For example in many languages floating point numbers in code default to adouble
. To down-convert you either need an explicit cast, or the suffix to fix it.float smallPi = 3.14159F;
. Depends on your language honestly.