How to Read Complicated Declarations in C
The right-left rule decodes any C declaration in a predictable sequence. Step-by-step examples for pointers, arrays, and function pointers, with cdecl cross-checks.
C pointer declarations stop students cold during placement aptitude rounds, not because the rules are hard, but because no one taught the reading order. One rule, applied mechanically, resolves every declaration.
The Right-Left Rule: Reading Every Declaration Systematically
The right-left rule has three steps:
- Step 1: Find the identifier (the variable or function name).
- Step 2: Read what is immediately to the right of the identifier. If you see
[], the current item is an array. If you see(), it is a function. - Step 3: Read what is immediately to the left. If you see
*, the current item is a pointer. - Repeat: Move outward through any enclosing parentheses and continue alternating right-left until you reach the base type (
int,char,void, etc.).
One precedence rule governs which binding wins when there is a conflict:
| Operator | Meaning | Precedence |
|---|---|---|
() around a name | Groups before anything else | Highest |
[] | Array subscript | Second |
() after a name | Function call | Second (same as []) |
* | Pointer to | Lowest |
The parentheses are the key. Without them, [] and () beat *. With them, you can force * to bind first, changing the declaration’s meaning entirely. That single insight distinguishes students who read declarations correctly from those who guess.
For the complete syntax rules behind pointer declarations, see the cppreference pointer declaration reference.
Four Patterns That Cover Most Placement MCQs
TCS NQT, AMCAT, and CoCubes C sections each include 2 to 4 pointer-declaration MCQs. These four patterns account for the majority of them. Apply the right-left rule to each one before reading the answer.
Pointer to an integer
int *ptr;
- Start at
ptr. Right: nothing (end of declaration). Left:*— ptr is a pointer. - Continue left:
int— it points to int. - Reading:
ptris a pointer to int.
Array of pointers to integers
int *arr[10];
- Start at
arr. Right:[10]— arr is an array of 10 elements. - Left:
*— each element is a pointer. - Continue left:
int— each pointer points to int. - Reading:
arris an array of 10 pointers to int.
Pointer to an array of integers
int (*ptr)[10];
- The parentheses bind first. Start at
ptr. Left:*— ptr is a pointer. - Now exit the parentheses. Right:
[10]— it points to an array of 10 elements. - Left:
int— each element is int. - Reading:
ptris a pointer to an array of 10 integers.
This is the declaration that trips up the most students. int *ptr[10] and int (*ptr)[10] look nearly identical. One is an array of pointers; the other is a pointer to an array. The parentheses change the meaning completely.
Pointer to a function returning an integer
int (*funcPtr)();
- Parentheses bind first. Start at
funcPtr. Left:*— funcPtr is a pointer. - Exit parentheses. Right:
()— it points to a function. - Left:
int— the function returns int. - Reading:
funcPtris a pointer to a function returning int.
Compare with int *funcPtr() (no inner parentheses): funcPtr would be a function returning a pointer to int. One pair of parentheses, entirely different type.
Common MCQ trap: the parentheses test
Placement tests exploit the visual similarity between int *arr[10] and int (*arr)[10]. The standard question format presents two declarations and asks which refers to the pointer-to-array and which to the array-of-pointers. A reliable test: if the name is inside parentheses with a *, the parentheses dominate, so the outermost meaning is “pointer.” If the name is bare, [] dominates, so the outermost meaning is “array.”
For worked MCQs that test these patterns directly, the C programming MCQ set for placement prep covers pointer passing, double pointers, and full code traces used in service-tier placement rounds.
Going Deeper: Function Pointers and Arrays of Them
These patterns appear in technical interviews at product companies and in elite-track rounds (Wipro Elite, TCS Digital). They also appear in GATE CS and in senior-engineer written rounds for embedded and systems roles.
Array of function pointers
int (*funcArray[5])();
- Start at
funcArray. Right:[5]— funcArray is an array of 5 elements. - Left:
*— each element is a pointer. - Exit the outer parentheses. Right:
()— each pointer points to a function. - Left:
int— each function returns int. - Reading:
funcArrayis an array of 5 pointers to functions returning int.
A working example using the dispatch-table pattern:
#include <stdio.h>
int add(void) { return 10; }
int subtract(void) { return 5; }
int main(void) {
int (*funcArray[2])(void);
funcArray[0] = add;
funcArray[1] = subtract;
printf("%d\n", funcArray[0]()); /* 10 */
printf("%d\n", funcArray[1]()); /* 5 */
return 0;
}
Pointer to a function returning a pointer to int
int *(*funcPtr)();
- Parentheses bind first. Left:
*— funcPtr is a pointer. - Exit parentheses. Right:
()— it points to a function. - Left:
*— the function returns a pointer. - Continue left:
int— the pointer points to int. - Reading:
funcPtris a pointer to a function that returns a pointer to int.
A minimal working example:
int value = 100;
int *getPointer(void) { return &value; }
int main(void) {
int *(*funcPtr)(void) = getPointer;
printf("%d\n", *funcPtr()); /* 100 */
return 0;
}
Pointer to function returning pointer to array
int (*(*fp)())[10];
Apply the rule step by step:
- Start at
fp. Left of inner*: fp is a pointer. - Exit inner parentheses. Right:
()— it points to a function. - Left:
*— the function returns a pointer. - Exit outer parentheses. Right:
[10]— the pointer points to an array of 10. - Left:
int— each element is int. - Reading:
fpis a pointer to a function returning a pointer to an array of 10 integers.
Pointer to pointer to int
int **ptr;
- Start at
ptr. Right: nothing. Left:*— ptr is a pointer. - Continue left:
*— the pointer points to a pointer. - Continue left:
int— the inner pointer points to int. - Reading:
ptris a pointer to a pointer to int.
Double pointers appear in functions that must modify a pointer variable in the calling scope, and in dynamically allocated 2D arrays. They are common in MCQs that ask candidates to trace ++param versus ++(*param). The distinction being tested is between incrementing the pointer itself and incrementing the value it points to.
Using cdecl as a Sanity Check
cdecl.org is a free web tool that converts C declarations to plain English, and vice versa. It has been accurate for standard C declarations since its initial release in the 1980s and is still actively maintained.
To decode int (*(*fp)())[10], type this into the cdecl input box:
explain int (*(*fp)())[10];
Output:
declare fp as pointer to function returning pointer to array 10 of int
To go the other direction, describe the type you want:
declare ptr as pointer to function returning pointer to int
Output:
int *(*ptr)()
The command-line version of cdecl is available in most Linux distributions (apt install cdecl). It accepts the same input syntax and produces the same output.
cdecl catches transcription mistakes and confirms readings of especially long declarations. FACE Prep recommends using it as a cross-check after applying the rule manually, not as a substitute. Placement tests don’t provide cdecl, and the skill of reading declarations without a tool is what the MCQs are actually testing.
Applying the Rule to Interview-Level Declarations
Two patterns appear in senior-engineer and off-campus technical interview contexts. Both decompose by the same rule. Only the nesting depth increases.
Signal-handler pointer (POSIX standard library)
The C standard library’s signal function has one of the most cited declarations in common use:
void (*signal(int sig, void (*handler)(int)))(int);
Apply the rule:
- The function name is
signal. signal(int sig, void (*handler)(int))— signal is a function taking two parameters.- The return type sits outside the inner parentheses:
void (*...)(int)— it returns a pointer to a function taking int and returning void. - The second parameter
void (*handler)(int)is itself a pointer to a function taking int and returning void. - Reading:
signalis a function taking an int and a pointer-to-function(int)->void, and returning a pointer to a function taking int and returning void.
Complex? Yes. But every layer follows the same rule.
Reading declarations from interview whiteboard questions
When a declaration appears on a whiteboard, read it aloud in steps: “fp is a pointer to a function that returns a pointer to an array of 10 integers.” Decomposing out loud during a technical interview shows the interviewer that you understand the type system, not just C syntax. Interviewers in systems and embedded roles have confirmed this is one of the few places where narrating your thinking is expected.
For an overview of how C declarations appear alongside other reasoning questions in placement aptitude rounds, see aptitude test pattern for placement rounds.
The Bridge to LLM-Assisted Code Tools
Placement tests still weight C declarations because they measure whether a student can reason about types under pressure, without a compiler. That type-reasoning skill transfers directly: production AI inference libraries like TensorFlow and PyTorch expose C extension APIs, and Python C bindings use exactly these declaration patterns in their header files.
If you’ve traced int (*(*fp)())[10] manually and want to see how the same reasoning applies when writing AI tool integrations or debugging compiled Python extensions, TinkerLLM is the practical next step at ₹299.
Primary sources
Frequently asked questions
What is the right-left rule for reading C declarations?
Start at the identifier (variable name). Read what is to the right first — if you see [], it is an array; if you see (), it is a function. Then read to the left — if you see *, it is a pointer. Repeat, working outward through any enclosing parentheses, until the base type (int, char, etc.) is reached.
What does int (*ptr)[10] mean in C?
ptr is a pointer to an array of 10 integers. The parentheses around *ptr force the pointer to bind before the array brackets, so ptr points to a whole array, not to a single int inside it.
How is int *arr[10] different from int (*arr)[10]?
int *arr[10] is an array of 10 pointers to int — arr itself is the array, and each element holds an address. int (*arr)[10] is a pointer to an array of 10 integers — arr is the pointer, and it points to a 10-element int array. The parentheses change which binding happens first.
What does int (*funcPtr)() declare in C?
funcPtr is a pointer to a function that takes no specified parameters and returns int. Without the parentheses, int *funcPtr() would declare funcPtr as a function returning a pointer to int — the meaning flips entirely.
How do I use cdecl to decode a complicated C declaration?
Go to cdecl.org and type: explain int (*(*fp)())[10]; — cdecl responds with 'declare fp as pointer to function returning pointer to array 10 of int'. You can also type a description in English and ask cdecl to generate the C declaration.
What is an array of function pointers in C, and when is it used?
int (*funcArray[5])() declares funcArray as an array of 5 pointers to functions returning int. It is used to build dispatch tables — a common pattern in embedded systems and event-driven code where a set of callbacks must be selected at runtime by index.
Do complicated pointer declarations appear in placement aptitude tests?
Yes. TCS NQT, AMCAT, and CoCubes placement tests include 2 to 4 C pointer and declaration MCQs per paper. The typical question presents a declaration and asks what the variable is, or asks which of two similar declarations (like int *arr[5] vs int (*arr)[5]) refers to an array of pointers vs a pointer to an array.
How do I read int *(*f())(int) step by step?
Start at f: f is a function (the () to the right). Read left: it returns a pointer (*). Now the outer structure: that pointer points to a function taking int (the (int) to the right). Read left: that function returns a pointer to int. So f is a function returning a pointer to a function that takes int and returns a pointer to int.
A self-paced playground for building with LLMs.
TinkerLLM is FACE Prep's sister property. A guided environment for shipping real LLM applications, the kind of project that earns a paragraph on your resume, not a line.
Try TinkerLLM (₹299 launch)