I was not sure what to call these flags, but what I am referring to is:
#define TEST_DEF 50000U //<- the "U" here
Google searching when you are not familiar with the jargon used to describe your question is futile.
What I am trying to do is use these constant definitions and make sure the value is only of a certain length, namely 8 or 16 bits.
How can I do this and what is it referred to as?
There are five integer literal suffixes in C: u
, l
, ul
, ll
, and ull
. Unlike nearly everything else in C they are case insensitive; also, ul
and ull
can be written as lu
and llu
respectively (however, lul
is not acceptable).
They control the type of the constant. They work approximately like this:
literal │ type
────────┼───────────────────────
500 │ int
500u │ unsigned int
500l │ long int
500ul │ unsigned long int
500ll │ long long int
500ull │ unsigned long long int
This is only an approximation, because if the constant is too large for the indicated type, it is "promoted" to a larger type. The rules for this are sufficiently complicated that I'm not going to try to describe them. The rules for "promoting" hexadecimal and octal literals are slightly different than the rules for "promoting" decimal literals, and they are also slightly different in C99 versus C90 and different again in C++.
Because of the promotion effect, is not possible to use these suffixes to limit constants to any size. If you write 281474976710656
on a system where int
and long
are both 32 bits wide, the constant will be given type long long
even though you didn't say to do that. Moreover, there are no suffixes to force a constant to have type short
nor char
. You can indicate your intent with the [U]INT{8,16,32,64,MAX}_C
macros from <stdint.h>
, but those do not impose any upper limit either, and on all systems I can conveniently get at right now (OSX, Linux), *INT8_C
and *INT16_C
actually produce values with type (unsigned) int
.
Your compiler may, but is not required to, warn if you write ((uint8_t) 512)
or similar (where 512 is a compile-time constant value outside the range of the type. In C11 you can use static_assert
(from <assert.h>
) to force the issue but it might be a bit tedious to write.
For integers, the section of the standard (ISO/IEC 9899:2011 — aka C2011 or C11) defining these suffixes is:
§6.4.4.1 Integer constants
Where it defines the integer-suffixes:
integer-suffix:
unsigned-suffix long-suffixopt
unsigned-suffix long-long-suffix
long-suffix unsigned-suffixopt
long-long-suffix unsigned-suffixopt
unsigned-suffix: one of
u U
long-suffix: one of
l L
long-long-suffix: one of
ll LL
The corresponding suffixes for floating point numbers are f
, F
, l
and L
(for float
and long double
).
Note that it would be perverse to use l
because it is far too easily confused with 1
, so the qualifiers are most often written with upper-case letters.
If you want to create integer literals that are of a given size, then the facilities to do so are standardized by <stdint.h>
(added in C99).
The header (conditionally) defines fixed-size types such as int8_t
and uint16_t
. It also (unconditionally) provides minimum-sized types such as int_least8_t
and uint_least16_t
. If it cannot provide exact types (perhaps because the word size is 36 bits, so sizes 9, 18 and 36 are handled), it can still provide the least types.
It also provide macros such as INT8_C
which ensure that the argument is an int_least8_t
value.
Hence, you could use:
#include <stdint.h>
#define TEST_DEF UINT16_C(50000)
and you are guaranteed that the value will be at least 16 bits of unsigned integer, and formatted/qualified correctly.
§7.20.4 Macros for integer constants
¶1 The following function-like macros expand to integer constants suitable for initializing
objects that have integer types corresponding to types defined in <stdint.h>
. Each
macro name corresponds to a similar type name in 7.20.1.2 or 7.20.1.5.
¶2 The argument in any instance of these macros shall be an unsuffixed integer constant (as
defined in 6.4.4.1) with a value that does not exceed the limits for the corresponding type.
¶3 Each invocation of one of these macros shall expand to an integer constant expression
suitable for use in #if preprocessing directives. The type of the expression shall have
the same type as would an expression of the corresponding type converted according to
the integer promotions. The value of the expression shall be that of the argument.
7.20.4.1 Macros for minimum-width integer constants
¶1 The macro INTN_C(value)
shall expand to an integer constant expression
corresponding to the type int_leastN_t
. The macro UINTN_C(value)
shall expand
to an integer constant expression corresponding to the type uint_leastN_t
. For
example, if uint_least64_t
is a name for the type unsigned long long int
,
then UINT64_C(0x123)
might expand to the integer constant 0x123ULL
.
This is an unsigned literal (U is suffix). See: http://en.cppreference.com/w/cpp/language/integer_literal