The * indirection operator is a unary operator, meaning its operand is to the right of the operator, as in *p.
C declarations are broken into two major sections - a sequence of declaration specifiers (type specifiers, storage class specifiers, type qualifiers, etc.) followed by a comma-separated list of declarators. A declarator introduces the name of the thing being declared, along with information about that thing’s array-ness, pointer-ness, and function-ness. In the declaration statement
int a[10], *p, f(void);
the declaration specifier is int and the declarators are a[10], *p, and f(void). Note that the * is bound to the declarator, not the type specifier. Because it’s a unary operator and token on its own, you don’t need whitespace to separate the type specifier from the identifier - all of
int *p;
int* p;
int*p;
int * p;
are equally valid, and all are interpreted as int (*p); - the operand of * is always p, not int or any other type specifier1.
The type of a is "10-element array of int", which is fully specified by the combination of the int type specifier and by the [10] in the declarator. Similarly the type of p is "pointer to int", which again is fully specified by the combination of the type specifier and the * operator in the declarator. And the type of f is "function returning int" by the same reasoning.
This is key - there is no type specifier for pointer, array, or function types - they can only be specified by a combination of one or more declaration specifiers and a declarator.
So how do we specify pointer types (or array or function types) in a cast? Basically, we write a declaration composed of declaration specifiers and a declarator, but with no identifier. If we want to cast something as a pointer to int, we write it as a regular pointer declaration with an unnamed variable - (int *).
- This is why I’m not fond of the C++ convention of writing pointer declarations as
T* p;; it doesn’t follow the syntax, and it’s inconsistent - a declaration like int* a[N]; is schizophrenic. It also introduces confusion when you write something like T* p, q; because it looks like you intend to declare both p and q as pointers, but only p is.