Operators: sizeof, _Alignof, Cast, Conditional, Comma
This chapter covers the remaining operators that are easy to misunderstand: sizeof, _Alignof, casts, the conditional operator, and the comma operator.
Why This Matters
sizeof and _Alignof are compile-time operators with subtle operand semantics. Casts are a frequent source of undefined behavior and aliasing violations. The conditional operator has type rules that surprise even experienced programmers.
Prerequisites
c.core.8— expressions and evaluation.
Core Concept
sizeof
sizeof yields the size, in bytes (as a size_t), of its operand:
sizeof(type)— size of a type.sizeof expression— size of the expression's type (the expression is
not evaluated).
sizeof returns sizeof(char) == 1 by definition. The result is a compile-time constant for all types except VLAs (c.arr.vla).
sizeof(int) /* 4 on most systems */
sizeof x /* size of x's type */
sizeof *p /* size of the pointed-to type; p is not dereferenced */
The sizeof *p idiom is safe even if p is NULL, because *p is not evaluated.
_Alignof (C11)
_Alignof(type) yields the alignment requirement of a type, as a size_t. The header <stdalign.h> defines alignof as a macro for _Alignof.
_Alignof(int) /* 4 on most systems */
Casts
A cast explicitly converts a value to a specified type:
(int)3.14 /* 3 (truncates toward zero) */
(void *)0 /* null pointer of type void* */
(unsigned char)300 /* 44 (wraps modulo 256) */
Casts are powerful and dangerous. Many casts are fine (numeric conversions, void * conversions), but pointer casts that violate alignment or aliasing rules are undefined behavior.
Conditional operator
cond ? a : b evaluates cond; if true, evaluates and yields a; otherwise evaluates and yields b. Only one of a and b is evaluated.
The result type is determined by the *common type* of a and b (following the usual arithmetic conversions, plus special rules for pointers).
Comma operator
expr1, expr2 evaluates expr1 (discarding its value), then evaluates and yields expr2. It has the lowest precedence of all operators.
int x = (f(), 5); /* calls f(), then sets x to 5 */
Note: the comma in a function argument list is a *separator*, not the comma operator.
Syntax
sizeof (type-name)
sizeof expression
_Alignof (type-name)
(type-name) expression
condition ? expression1 : expression2
expression1 , expression2
Examples
sizeof does not evaluate
#include <stdio.h>
int main(void)
{
int x = 0;
size_t n = sizeof(x++); /* x++ is NOT evaluated */
printf("%zu %d\n", n, x); /* x is still 0 */
return 0;
}
Expected output: 4 0 (assuming 4-byte int).
Conditional operator type
#include <stdio.h>
int main(void)
{
int a = 1;
double b = 2.5;
printf("%f\n", 1 ? a : b); /* common type is double */
return 0;
}
Expected output: 1.000000 (the int is converted to double).
Comma operator vs. argument separator
int x = (1, 2, 3); /* comma operator: x is 3 */
f(1, 2, 3); /* three arguments; commas are separators */
How It Works
sizeof and _Alignof are resolved at compile time (except VLA sizeof). A cast performs a conversion. The conditional operator performs a branch plus a conversion to the common type. The comma operator sequences two evaluations.
Variations
sizeof with arrays and pointers
int arr[10];
sizeof(arr) /* 10 * sizeof(int): the whole array */
sizeof(&arr[0]) /* size of a pointer, NOT the array */
This distinction is covered deeply in c.arr.decay.
Cast categories
- Numeric casts: change representation/range.
- Pointer casts: reinterpret an address as another pointer type.
- **
void *casts:** the only portable generic object pointer conversion.
Common Mistakes
- Assuming
sizeofevaluates its operand. - Using
sizeofon an array parameter and expecting the array size (array
parameters decay to pointers, c.arr.decay).
- Casting a pointer to an incompatible type and dereferencing it (aliasing UB).
- Confusing the comma operator with the argument separator.
Undefined Behavior
- Casting a pointer to a type with stricter alignment and dereferencing the
misaligned result is UB. VERIFIED
- Accessing an object through an lvalue of an incompatible type violates strict
aliasing (c.obj.aliasing). VERIFIED
- Casting a floating value to an integer type when the value is out of range
is UB. VERIFIED
Portability
sizeofresults are implementation-defined (exceptsizeof(char) == 1)._Alignofis C11 and later.- The result type of the conditional operator follows portable standard rules
but can be surprising when pointers are involved.
Under the Hood
sizeof and _Alignof produce constants at compile time. Casts produce conversion instructions (e.g., cvttsd2si for double→int on x86) or no code at all for pointer reinterpretations. The conditional operator compiles to a branch or, when possible, a conditional-move instruction.
Practical Usage
- Use
sizeof *pwhen allocating:malloc(sizeof *p)avoids type/name drift. - Use casts sparingly; when you cast a pointer, know the aliasing and alignment
rules.
- Use the comma operator only in
forloops or deliberate sequencing, where
it is clear.
Exercises
1. Demonstrate that sizeof(x++) does not modify x. 2. Write a macro ARRAY_LEN(a) using sizeof that returns the number of elements in a fixed array, and explain why it does not work on a pointer. 3. Determine the result type of cond ? (int)x : (double)y and verify by printing. 4. Show the difference between (a, b, c) and f(a, b, c).
Deep Challenge
Explain why malloc(sizeof *p) is preferred over malloc(sizeof(struct T)), and write a small generic allocation macro that works for any pointer type while preserving the correct size. Discuss any pitfalls with sizeof and arrays.
Related Concepts
c.arr.decay— sizeof and arrays.c.obj.aliasing— pointer casts and aliasing.c.types.uac— conversions in conditional operator.c.mem.malloc— sizeof in allocation.
References
- ISO/IEC 9899:2018 §6.5.3.4 (sizeof), §6.5.3.2 (casts), §6.5.15
(conditional), §6.5.17 (comma), §6.2.8 (alignment).
Verification
sizeofdoes not evaluate its operand.VERIFIEDsizeof(char)is 1.VERIFIED_Alignofis C11.VERIFIED- Conditional operator common-type rules are standard.
VERIFIED - No example was executed during generation unless noted. `Execution not
verified.`
Progress
- [ ] Read
- [ ] Understand
- [ ] Complete examples
- [ ] Complete exercises
- [ ] Complete deep challenge
Concept checkboxes
- [ ] sizeof (type and expression forms)
- [ ] _Alignof
- [ ] Casts and their dangers
- [ ] Conditional operator and common type
- [ ] Comma operator vs. argument separator
Mastery levels
| Concept | Current level (0–8) | Target level |
|---|---|---|
| c.ops.sizeof | 0 | 5 |
| c.ops.cast | 0 | 5 |
| c.ops.conditional | 0 | 5 |
| c.ops.comma | 0 | 4 |