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 ) statementdo statement while ( expression ) ;for ( expressionopt ; expressionopt ; expressionopt ) statement-
for ( declaration expressionopt ; expressionopt ) statementsince C99 - selection-statement
if ( expression ) statementif ( 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:
_Boolatomic_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 boolcharclock_tdoubledouble _Complexdouble _Imaginarydouble complexdouble imaginarydouble_terrno_tFILE *floatfloat _Complexfloat _Imaginaryfloat complexfloat imaginaryfloat_tintint16_tint32_tint64_tint8_tint_fast16_t int_fast32_t int_fast64_t int_fast8_t int_least16_t int_least32_t int_least64_t int_least8_t intmax_tintptr_tlonglong doublelong double _Complexlong double _Imaginarylong double complexlong double imaginarylong longptrdiff_trsize_tshortsig_atomic_t signed charsize_ttime_tuint16_tuint32_tuint64_tuint8_tuint_fast16_t uint_fast32_t uint_fast64_t uint_fast8_t uint_least16_t uint_least32_t uint_least64_t uint_least8_t uintmax_tuintptr_tunsignedunsigned charunsigned longunsigned long longunsigned shortwchar_twctrans_twctype_twint_t