How to interpret complex C++ variable declarations
From int* p to int (*(*p)[])()
C++ variable definition can be very complex when *, & and nested brackets exist. This tutorial lists some examples from easy to advanced level to help you walk you through each of them and understand how we should interpret them in a more systematic way.
Example 1
Definition like below is quite easy and straightfoward. It declares a pointer p that points to an Integer.
p itself exists on stack but the Integer that it points to is on heap memory.
1 | int* p = new int; |
Example 2
1 | int* v[5]; |
This example represents an array of 5 pointers. These 5 pointers are pointing to Integers.
Here’s a breakdown:
- int*: Indicates that the elements of the array are pointers to integers.
- v[5]: Indicates that v is an array with 5 elements.
Example 3
1 | int (*v)[5]; |
This example represents a pointer v to an array of 5 Integers.
Here’s a breakdown:
- (*v): Indicates that v is a pointer.
- [5]: Indicates that the elements pointed to by v form an array of size 5.
- int: Indicates that the elements of the array are of type int.
Example 5
1 | int p(); // p is a function that returns a int value |
Here’s a breakdown:
- (*p)(): Indicates that p is a pointer to a function.
- int: Specifies that the function returns an integer.
- (): Indicates that the function takes no arguments.
Example 6
1 | int (*v[])(); |
It represents an array of pointers. Each pointer points to functions that return int values.
Here’s a breakdown:
- v[]: Indicates that v is an array.
- (*v[])(): Indicates that the elements of the array are pointers to functions.
- int: Specifies that the functions return integers.
- (): Indicates that the functions take no arguments.
A simple demo code
1 | // Define two functions that match the pointer type |
Example 7
1 | int (*(*v)[])(); |
It declares a pointer v to an array of pointers. Each pointer points to functions returning integers.
Here’s a breakdown:
- (*v)[]: This part declares a pointer to an array. The *v declares a pointer, and [] indicates that this pointer is pointing to an array.
- int ()(): This part declares a pointer to a function. The int is the return type of the function, () indicates it’s a pointer to a function, and () indicates that the function takes no parameters.
A simple demo code:
1 | int func1() { |
Example 8
1 | int* p(); // function p returns a pointer to an Integer |
Example 9
1 | int const a; |
They are equivalent and a can not be modified.
Example 10
1 | int const *p; // p is a pointer to a const int |
1 | int main() { |
Conclusion
right-to-left rule
Start reading the declaration from the innermost parentheses, go right, and then go left. When you encounter parentheses, the direction should be reversed. Once everything in the parentheses has been parsed, jump out of it. Continue till the whole declaration has been parsed.
for example:
1 | float ( * ( *p()) [] )(); |
- Start from the variable name ————————– p
- Go right, find () ———- p is a function
- Nothing to the right, go left and find * ———— returns a pointer
- Go right, find [] ————– to an array
- Go left, find * ————— pointers
- Go right, find () ———- to functions
- Go left, find float ———- return float
So, the result is: p is a function that returns a pointer. The pointer points to an array of pointers. Each pointer points to functions that return float value.
References
How to interpret complex C++ variable declarations
http://chuzcjoe.github.io/2023/11/12/cpp-how-to-interpret-complex-variable-definition/