The scalar types consist of the arithmetic types and the pointer types. [That can't be right. Arithmetic types now include complex types too, and they aren't scalar in the mathematical sense.]
A value of one scalar type can be converted to another
scalar type, possibly with some loss of information. In
particular, arithmetic types can be converted between each
other, and any object pointer can be converted to and from
void *
.
Sometimes, an explicit cast is necessary to tell
the compiler that the conversion is intended:
- cast-expression
( type-name ) cast-expression
If they exist, uintptr_t
and intptr_t
are integer types capable of
holding object pointers without loss.
A cast might be necessary to force a certain variation of an operation to take place. For example:
int x, y; double q = x / y; double r = (double) x / y;
Although q
is of type double
, it will
hold the result of an integer division. In contrast,
r
will hold the ratio of x
and y
, because the value
of x
was first cast to double
, which
forced the division operator /
to
perform real division. Note that the precedence of the cast is higher than
that of /
, so the expression is
equivalent to ((double) x) /
y
.
Finally, a cast might be useful, even when not necessary, to silence a compiler warning about loss of information:
double y; /* The compiler might warn that fractional data will be lost. */ int x1 = y; /* This will silence most compilers. */ int x2 = (int) y;
Casting can only be done between scalar types.
Scalar types are required as the operands of the following operators:
- unary-expression
unary-operator cast-expression
- unary-operator
!
- logical-OR-expression
logical-OR-expression || logical-AND-expression
- logical-AND-expression
logical-AND-expression && inclusive-OR-expression
Scalar types are also required in the controlling
expressions of the conditional operator, loops and if
:
- conditional-expression
logical-OR-expression ? expression : conditional-expression
- iteration-statement
while ( expression ) statement
do statement while ( expression ) ;
for ( expressionopt ; expressionopt ; expressionopt ) statement
-
for ( declaration expressionopt ; expressionopt ) statement
since C99 - selection-statement
if ( expression ) statement
if ( expression ) statement else statement
The macro assert
requires an expression of
scalar type as its argument.
wctype_t
and wctrans_t
are guaranteed to be
scalar types.
The following types are guaranteed to be scalar; some are variations or aliases of others, and other, non-standard types may exist:
_Bool
atomic_
bool atomic_
char atomic_
char16_t atomic_
char32_t atomic_
int atomic_
int_ fast16_t atomic_
int_ fast32_t atomic_
int_ fast64_t atomic_
int_ fast8_t atomic_
int_ least16_t atomic_
int_ least32_t atomic_
int_ least64_t atomic_
int_ least8_t atomic_
intmax_t atomic_
intptr_t atomic_
llong atomic_
long atomic_
ptrdiff_t atomic_
schar atomic_
short atomic_
size_t atomic_
uchar atomic_
uint atomic_
uint_ fast16_t atomic_
uint_ fast32_t atomic_
uint_ fast64_t atomic_
uint_ fast8_t atomic_
uint_ least16_t atomic_
uint_ least32_t atomic_
uint_ least64_t atomic_
uint_ least8_t atomic_
uintmax_t atomic_
uintptr_t atomic_
ullong atomic_
ulong atomic_
ushort bool
char
clock_t
double
double _Complex
double _Imaginary
double complex
double imaginary
double_t
errno_t
FILE *
float
float _Complex
float _Imaginary
float complex
float imaginary
float_t
int
int16_t
int32_t
int64_t
int8_t
int_
fast16_t int_
fast32_t int_
fast64_t int_
fast8_t int_
least16_t int_
least32_t int_
least64_t int_
least8_t intmax_t
intptr_t
long
long double
long double _Complex
long double _Imaginary
long double complex
long double imaginary
long long
ptrdiff_t
rsize_t
short
sig_
atomic_t signed char
size_t
time_t
uint16_t
uint32_t
uint64_t
uint8_t
uint_
fast16_t uint_
fast32_t uint_
fast64_t uint_
fast8_t uint_
least16_t uint_
least32_t uint_
least64_t uint_
least8_t uintmax_t
uintptr_t
unsigned
unsigned char
unsigned long
unsigned long long
unsigned short
wchar_t
wctrans_t
wctype_t
wint_t