`typeof(3*x) y = 3*x;` declares `y` with the type of `3*x`, then initializes it with that expression. `typeof` supplies a type where a typedef name could otherwise appear; it does not evaluate its expression operand. The initializer is separate and does evaluate `3*x`. In unusual cases, this style can lead to an evaluation concern, so prefer `auto` for variable declarations. section 18.3.2
#define static_assert_compatible(A, B, REASON) \
static_assert(_Generic((typeof(A)*)nullptr, \
typeof(B)*: true, \
default: false), \
"expected compatible types: " REASON ", have " #A " and " #B "")
A type-compatibility macro uses `typeof(A)*` and `typeof(B)*` where `_Generic` needs types. The selection tests the pointer types without evaluating `A` or `B`. Its stated use is checking compatible non-array object types inside other macros. section 18.3.2
This is where `typeof` goes beyond `auto`: it can turn the type of a macro argument into a type name for a cast or generic selection. It can also help choose a function according to types derived from multiple arguments, or cast a generic operation’s result back to a type derived from its arguments. `typeof_unqual` is available when qualifiers must be handled differently. section 18.3.2 section 18.5
enum eInt : signed int { dInt = 0, uInt = 0xFFFF'FFFF, };
typedef enum eInt eInt;
enum eSig : typeof(4'294'967'295) { dSig = 0, uSig = 4'294'967'295, };
typedef enum eSig eSig;
enum e32 : uint32_t { d32 = 0, u32 = 0xFFFF'FFFF, };
typedef enum e32 e32;
An enumeration can use `typeof(4'294'967'295)` to specify that its underlying type is the type of this decimal constant, which is signed. This states a different intent from choosing `uint32_t` or relying on an ambiguous underlying type. section 5.6.2
TAKEAWAY: Use `auto` for ordinary inferred variable declarations. Reach for C23 `typeof` when a type derived from an expression must appear in a position that requires a type. section 18.3.2


