Data Types, Declarations, and Type Conversions
This domain tests whether you can name the type and value of an expression after C's implicit conversions, and whether you know which conversions are undefined rather than merely surprising.
The type system in one pass
- Integer types:
char,short,int,long,long long, each signed or unsigned;_Bool(include<stdbool.h>forbool,true,false). Whether plaincharis signed is implementation-defined. <stdint.h>supplies exact-widthint32_t, minimum-widthint_least32_t, fast types, andintptr_t/uintmax_t.sizeofyieldssize_t, an unsigned type; pointer subtraction yieldsptrdiff_t.- Qualifiers:
const,volatile, andrestrict(pointers only).volatileforbids optimization of the access; it is not a threading primitive.
Integer promotions and the usual arithmetic conversions
- Any type of rank lower than
intis promoted tointifintcan hold all its values, otherwise tounsigned int. - If either operand is
long double,double, orfloat, the other converts to it. - Otherwise, if both operands share a signedness, the lower rank converts to the higher rank.
- If the unsigned operand's rank is greater than or equal to the signed one's, the signed operand converts to unsigned.
- Otherwise the unsigned operand converts to the signed type if that type can represent all its values; if not, both convert to the unsigned counterpart of the signed type.
Worked example
int i = -1;
unsigned int u = 1;
if (i < u) puts("less"); else puts("not less");
Rule 4 applies: i converts to unsigned int, becoming 4294967295 on a 32-bit unsigned int, so the comparison is false and "not less" prints. The same rule makes sizeof(int) > -1 false, because -1 becomes SIZE_MAX.
Traps
- Signed integer overflow is undefined; unsigned overflow wraps modulo 2^N.
- Converting an out-of-range
doubleto an integer is undefined; in-range values truncate toward zero, so(int)-2.9is-2. char c = getchar();losesEOFand can pass a negative value totoupper, which is undefined - cast tounsigned char.- Removing
constthrough a pointer needs a cast and is only safe when the object is not actually const. printf("%u", i)with anintargument is undefined; match the conversion specifier to the promoted type.