C Mastery / Operators: sizeof, _Alignof, Cast, Conditional, Comma
Part 1 — The Core Language

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

Core Concept

sizeof

sizeof yields the size, in bytes (as a size_t), of its operand:

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

Common Mistakes

parameters decay to pointers, c.arr.decay).

Undefined Behavior

misaligned result is UB. VERIFIED

aliasing (c.obj.aliasing). VERIFIED

is UB. VERIFIED

Portability

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

rules.

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.

References

(conditional), §6.5.17 (comma), §6.2.8 (alignment).

Verification

verified.`

Progress

Concept checkboxes

Mastery levels

ConceptCurrent level (0–8)Target level
c.ops.sizeof05
c.ops.cast05
c.ops.conditional05
c.ops.comma04