Complex C declaration - c++

I was just going through some code on the Internet and found this:
float * (*(*foo())[SIZE][SIZE])()
How do I read this declaration? Is there a specific set of rules for reading such complex declarations?

I haven't done this in a while!
Start with foo and go right.
float * (*(*foo())[SIZE][SIZE])()
foo is a function with no arguments...
Can't go right since there's a closing parenthesis. Go left:
float * (*(* foo())[SIZE][SIZE])()
foo is a function with no arguments returning a pointer
Can't go left further, so let's cross the parentheses and go right again
float * (*(* foo())[SIZE][SIZE])()
float * (*(* foo())[SIZE][SIZE])()
float * (*(* foo())[SIZE][SIZE])()
foo is a function with no arguments returning a pointer to an array of SIZE arrays of SIZE ...
Closing parenthesis reached, left again to reach a pointer symbol:
float * (*(* foo())[SIZE][SIZE])()
foo is a function with no arguments returning a pointer to an array of SIZE arrays of SIZE pointers to ...
Left parenthesis again, so we cross it and go right again:
float *( *(* foo())[SIZE][SIZE])()
float *( *(* foo())[SIZE][SIZE])()
foo is a function with no arguments returning a pointer to an array of SIZE arrays of SIZE pointers to a function with no arguments...
And left to the end
float * ( *(* foo())[SIZE][SIZE])()
foo is a function with no arguments returning a pointer to an array of SIZE arrays of SIZE pointers to a function with no arguments returning a pointer to float
And whoever wrote that, please teach him to use typedef:
// Function that returns a pointer to float
typedef float* PFloatFunc ();
// Array of pointers to PFloatFunc functions
typedef PFloatFunc* PFloatFuncArray2D[SIZE][SIZE];
// Function that returns a pointer to a PFloatFuncArray2D
PFloatFuncArray2D* foo();

Standard rule: find the leftmost identifier and work your way out, remembering that [] and () bind before *:
foo -- foo
foo() -- is a function
*foo() -- returning a pointer
(*foo())[SIZE] -- to a SIZE-element array
(*foo())[SIZE][SIZE] -- of SIZE-element arrays
*(*foo())[SIZE][SIZE] -- of pointers
(*(*foo())[SIZE][SIZE])() -- to functions
* (*(*foo())[SIZE][SIZE])() -- returning pointers
float * (*(*foo())[SIZE][SIZE])(); -- to float
So imagine you have a bunch of functions returning pointers to float:
float *quux();
float *bar();
float *bletch();
float *blurga();
Let's say you want to store them in a 2x2 table:
float *(*tab[SIZE][SIZE])() = {quux, bar, bletch, blurga};
tab is a SIZE x SIZE array of pointers to functions returning pointers to float.
Now let's decide we want a function to return a pointer to that table:
float *(*(*foo())[SIZE][SIZE])()
{
static float *(*tab[SIZE][SIZE])() = {quux, bar, bletch, blurga};
return &tab;
}
Note that you could have several functions that build tables of different functions, or organize the same functions differently:
float *(*(*qwerbl())[SIZE][SIZE])()
{
static float *(*tab[SIZE][SIZE])() = {blurga, bletch, bar, quux};
return tab;
}
which is the only reason I can think of to do something like this. You shouldn't see types like this in the wild very often (although they do crop up occasionally, and I've been guilty of writing something similarly heinous).

According to cdecl.org
declare foo as function returning pointer to array SIZE of array SIZE
of pointer to function returning pointer to float
Use the spiral rule given by Luchian Grigore if you want to decode it by hand.

The best thing to do here is convert to a series of typedefs.
typedef float * fnReturningPointerToFloat();
typedef fnReturningPointerToFloat* fnArray[SIZE][SIZE];
fnArray* foo();

Generally, you could try cdecl.org but you'd need to substitute for SIZE
Say you swap SIZE for 12, you'd get:
declare foo as function returning pointer to array 12 of array 12 of
pointer to function returning pointer to float
I'm not sure that really helps you!
Two observations here:
I'm guessing that this code didn't have a comment beside it explaining what the purpose of it was (i.e. not the technical explanation of what it is but what it is achieving from a functional / business perspective) If a programmer needs to use something as complex as this, they should be good enough to explain to future maintainers what purpose it serves.
Certainly in C++ there are more obvious and probably safer ways of achieving the same thing.

This document gaves me the best clue about how to easily ready any C declaration :
http://c-faq.com/decl/spiral.anderson.html
There are three simple steps to follow:
Starting with the unknown element, move in a spiral/clockwise direction; when ecountering the following elements replace them with the corresponding english statements:
[X] or [] => Array X size of ... or Array undefined size of ...
(type1, type2) => function passing type1 and type2 returning ...
* => pointer(s) to ...
Keep doing this in a spiral/clockwise direction until all tokens have been covered.
Always resolve anything in parenthesis first!
Example :
+-------+
| +-+ |
| ^ | |
char *str[10];
^ ^ | |
| +---+ |
+-----------+
Question we ask ourselves: What is str?
``str is an...
- We move in a spiral clockwise direction starting with `str' and the first character we see is a `[' so, that means we have an array, so...
``str is an array 10 of...
- Continue in a spiral clockwise direction, and the next thing we encounter is the `*' so, that means we have pointers, so...
``str is an array 10 of pointers to...
- Continue in a spiral direction and we see the end of the line (the `;'), so keep going and we get to the type `char', so...
``str is an array 10 of pointers to char''
We have now ``visited'' every token; therefore we are done!

Although most of the answers above are good enough, there is a lack of complete set of rules for decoding complex C declarations. I have provided a complete set below to decode any complex C declaration. This set of rules is actually based on the precedence of operators. Rules such as right hand spiral rules can be thought of as a shortcut for these set of rules.
Before anything else we need to know a few things to decode the declaration.
'Basic Type' of a declaration
A C declaration always has only one basic declaration type. This is at the left most position of a declaration.
For example -
int a - basic type is 'int'
float *p - basic type is 'float'
char (*p)[3] - basic type is 'char'
Precedence and associativity
Next we need to know the precedence order of (), [], and * - dereference operator
(), [] - Associativity is left to right
* - Associativity is right to left
Phrase corresponding to each of the operator above
Next we need to know the decoded phrase corresponding to each operator. Examples ahead will make this point clear.
() - function returning
[SIZE] - array of SIZE
* - pointer to
Now follow the rules below to decode the declaration
Always write the variable name first followed by an 'is'.
For example -
int a - a is ...
float *p - p is ...
char (*p)[3] - p is ...
Always end with basic type
For example -
int a - a is ... int
float *p - p is ... float
char (*p)[3] - p is ... char
Now fill the part in between using the following sub-steps
Starting from the name, follow the operator precedence and associativity to choose next highest priority operator and append the phrase corresponding to it to the middle part of the decoded string.
Repeat the sub step above for the remaining declaration until the decoding process is complete
NOTE 1: For simplicity, I have ignored the arguments of the function however it can be included just after the phrase corresponding to ().
NOTE 2: Parenthesis(()) change the priority order of operators, just like in any arithmetic expression.
NOTE 3: You can use parenthesis in the decoded declaration to increase readability( I have done it in some examples below). Think of each set of () as a single unit.
NOTE 4: A n dimensional array is actually an array of array of ... (n-1 times) array. For ex - int A[2][3] - A is array of 2 (array of 3 int) i.e A is an array of 2 elements in which each element is an array containing 3 integers
Examples
int a - a is int
float *p - p is pointer to float
char (*p)[3] - p is pointer to array of 3 char
Some complex declaration examples
int **p[10] - p is array of 10 pointer to pointer to int
int (*p)[10] - p is pointer to array of 10 int
int *p(char *a) - p is function returning pointer to int
int (*p(char*a))[10] - p is function returning (pointer to (array of 10 int))
int *(*p)() - p is pointer to (function returning (pointer to int))
int (*p()[20])[10] - p is function returning (array of 20 (pointer to (array of 10 int)))
This set of rules can be used with const as well - const qualifier modifies the term to the left of it (if present) otherwise it modifies the term to the right of it.
const int *p[10] - p is array of 10 pointer to int const
int const *p[10] - p is array of 10 pointer to const int (this is same as 7th example)
int *const p[10] - p is array of 10 const pointer to int
Now a really complex example which will not find its use anywhere in practice but nevertheless can be used to demonstrate the decoding process
char *(*(**foo[][8])())[] - foo is array of (array of 8 (pointer to (pointer to (function returning (pointer to (array of (pointer to char)))))))
Now at last decoding for the declaration given in the question
float * (*(*foo())[SIZE][SIZE])() - foo is function returning (pointer to (array of SIZE (array of SIZE (pointer to (function returning pointer to float)))))
The following is the link for the article from which I read this decoding process
Example 10 has been taken from this article
http://www.unixwiz.net/techtips/reading-cdecl.html

from http://cdecl.org/
declare foo as function returning pointer to array SIZE of array SIZE of pointer to function returning pointer to float

Related

Passing a 2D Array to function in C++ [duplicate]

This question already has answers here:
Passing a 2D array to a C++ function
(18 answers)
How do I use arrays in C++?
(5 answers)
What is array to pointer decay?
(11 answers)
Closed 1 year ago.
I tried passing a 2D array to a function in C++ and I didn`t understand something:
//My array declaration:
int array[5][5]={{....}}; //I declared and filled the array with values
//My different function tries:
void passArr(int **array) //ERROR
void passArr(int *array[5]) //ERROR
void passArr(int *(*array)) //ERROR
void passArr(int (*(*array))) //ERROR
void passArr(int (*array)[5]) //WORKS
All errors were: [Error] cannot convert 'int (*)[5]' to 'int**' for argument '1' to 'void passArr(int**)'
Why do the errors show up and most importantly what is the difference between int *array[5] and int (*array)[5] when passing as an argument?
If int (*array)[5] worked, then why didn´t int *(*array) or int (*(*array))) also work?
In C and C++, a 2D array is an Array-of-Arrays. The first element of a 2D array is the first 1D array it contains. The conversion is specified in C++ Standard - Array-to-pointer Conversion [conv.array]
When you declared a plain-old 2D array as:
int array[5][5]
You have an array of int[5] arrays. As with any array, it is converted to a pointer to its first element on access. The first element being an array of int[5], so the resulting type is:
int (*)[5]
A pointer-to-array-of int[5]. So for your 2D array named array, that is:
int (*array)[5]
They're just different things. Reading from right to left might be helpful.
int array[5][5] -> array of array of int, could decay to pointer to array of int
int (*array)[5] -> pointer to array of int, could be converted from the above
int **array -> pointer to pointer to int
int *(*array) -> same as above
int (*(*array)) -> same as above
int *array[5] -> array of pointer to int
Also, in the "C++" language, it is strongly advisable to use one of the very-many "container classes" for this purpose. Or perhaps a class of your own devising.
"A simple pointer" has no way to convey that it is pointing to "a 2D array," nor what its dimensions are. The extent of its job-description is that it knows how to point to "a bunch of bytes, or nothing."
But if instead you provided your caller with a reference to a class, your caller could now "ask the class" for what it needed, "and the class would magically know." Just hand the class (X,Y) and you either get the right answer or a runtime exception is thrown. Every single time ... and by the way, efficiently.
This is a much more-robust way to write code, and it really is the reason why the C++ language was invented.
Versions 1,3, and 4 are all the same. Version 2 is also the same as 1,3, and 4, because when passing an array to a function the array decays to a pointer.
Version 2 can also be written
void passArr(int* array[5])
Which probably shows the association of the asterisk with the type more clearly: it is an array of five int-pointers. With the array decaying to a pointer, it becomes
void passArr(int** array)
All of them mean that the entry of the array are addresses, pointing to another array:
[ * | * | * | * | * ]
| | | | +-> [,,,,]
| | | +-> [,,,,]
And so on.
What you have is an array when each entry is an array of 5 ints, not a pointer to one (arrays bear a lot of resemblance with pointers, but they aren't pointers!)
Your matrix looks like this:
[ [1,2,3,4,5], [6,,,,], [,,,,], [,,,,], [,,,,] ]
So, array is a pointer to an int[5], not a pointer to pointer to int. And that is what the parentheses do in version 5: int (*array)[5]. This binds the asterisk closer to array.

Explaining sizeof(((rs_comm*)0)->ab[0]);

At xdn-project/digitalnote ./src/crypto/crypto.cpp file there is an error at line 338 when compiling (using cmake):
return sizeof(rs_comm) + pubs_count * sizeof(rs_comm().ab[0]);
^
error: value-initialization of incomplete type
‘Crypto::rs_comm:: []’
I found the solution on cryptonotefoundation/cryptonote:
return sizeof(rs_comm) + pubs_count * sizeof(((rs_comm*)0)->ab[0]);
I can play with Java JDK quite well, but currently at C++ need help :) It would be nice to see detail explanation of this code part:
sizeof(((rs_comm*)0)->ab[0]);
My questions are:
Asterisk after rs_comm - what its for?
0) - what is the purpose of 0 here?
The fragment of code:
struct rs_comm {
Hash h;
struct {
EllipticCurvePoint a, b;
} ab[];
};
static inline size_t rs_comm_size(size_t pubs_count) {
return sizeof(rs_comm) + pubs_count * sizeof(rs_comm().ab[0]);
}
sizeof is an operator that return the size of a specific type. It can work directly with a type or with an expression.
This part (rs_comm*)0 is taking 0 (0 is a valid null pointer constant) and casting it to a pointer of the struct rs_comm (or the class, I don't know the definition of rs_comm, but I am guessing).
Now, it is accessing using the -> operator to the data-member ab. ab has to be define as array, so it can get the first item in the array.
Because, sizeof doesn't really evaluate the expression but just figuring out the type and get the size of it.
So, the final result is the size of the first element in the array ab for the class/struct rs_comm.
So ab is an member of struct rs_comm, and is an array.
If you have a rs_comm object, i.e. rs_comm rs;, but you don't know the type of ab, you want to know its size, sizeof(rs.ab[0]) will do.
If you have a pointer to rs_comm, i.e. rs_comm *p_rs;, then sizeof(p_rs->ab[0]) will do the same thing.
If you don't have a rs_comm object nor a pointer to rs_comm, you can change a NULL pointer to a pointer to rs_comm, this is what ((rs_comm *)0) do.
Replace the p_rs in sizeof(p_rs->ab[0]) with ((rs_comm *)0), you get sizeof(((rs_comm *)0)->ab[0]).
sizeof(variable) .
return the size variable data type .
like
char x ;
cout << sizeof(x) ;
the result would be

Is * sign in frameSize.height*frameSize.width*nmixtures*(2 + 2*nchannels) means pointer or multiplication?

I'm never used C++ before, and I used OpenCV background subtraction MOG (Mixture of Gaussian) function in Python and I need to understand how the program works, the OpenCV program line 123 there's command bgmodel.create( 1, frameSize.height*frameSize.width*nmixtures*(2 + 2*nchannels), CV_32F );.. I found the .create function is to allocate new data from here with I assumed the parameter inside was (int ndims, const int* sizes, int type), my question is what the * mean, is it multiplication or pointer?
The asterisk (*) has three use cases:
The multiply operator: 2 * 3
A pointer type declaration: int* p;
Dereferencing a pointer (making it a reference to the value the
pointer is pointing to): *p = 6;
Example:
int i;
int* p = &i; // Sorry, introducing another confusion, taking the address of i
*p = 2 * 3;
// Now *p and i have the value 6
In the question, only multiplications are involved
If we look at your example:
bgmodel.create( 1, frameSize.height*frameSize.width*nmixtures*(2 + 2*nchannels), CV_32F );
We want to know if the * is a pointer dereference or is it multiplication. The form a a pointer dereference is
*pointer_type;
Which doesn't work here as every * is preceded by another variable. If we look at the syntax for multiplication we have:
some_type * some_type;
Now that matches what we have with variables on each side of the *
Now lets say you want to dereference a pointer and multiply it with something. To do that we will wrap the dereferencing in parentheses
some_type * (*pointer_type);

typedef of char pointers in c++ [duplicate]

What is the difference between the following declarations:
int* arr1[8];
int (*arr2)[8];
int *(arr3[8]);
What is the general rule for understanding more complex declarations?
int* arr[8]; // An array of int pointers.
int (*arr)[8]; // A pointer to an array of integers
The third one is same as the first.
The general rule is operator precedence. It can get even much more complex as function pointers come into the picture.
Use the cdecl program, as suggested by K&R.
$ cdecl
Type `help' or `?' for help
cdecl> explain int* arr1[8];
declare arr1 as array 8 of pointer to int
cdecl> explain int (*arr2)[8]
declare arr2 as pointer to array 8 of int
cdecl> explain int *(arr3[8])
declare arr3 as array 8 of pointer to int
cdecl>
It works the other way too.
cdecl> declare x as pointer to function(void) returning pointer to float
float *(*x)(void )
I don't know if it has an official name, but I call it the Right-Left Thingy(TM).
Start at the variable, then go right, and left, and right...and so on.
int* arr1[8];
arr1 is an array of 8 pointers to integers.
int (*arr2)[8];
arr2 is a pointer (the parenthesis block the right-left) to an array of 8 integers.
int *(arr3[8]);
arr3 is an array of 8 pointers to integers.
This should help you out with complex declarations.
int *a[4]; // Array of 4 pointers to int
int (*a)[4]; //a is a pointer to an integer array of size 4
int (*a[8])[5]; //a is an array of pointers to integer array of size 5
The answer for the last two can also be deducted from the golden rule in C:
Declaration follows use.
int (*arr2)[8];
What happens if you dereference arr2? You get an array of 8 integers.
int *(arr3[8]);
What happens if you take an element from arr3? You get a pointer to an integer.
This also helps when dealing with pointers to functions. To take sigjuice's example:
float *(*x)(void )
What happens when you dereference x? You get a function that you can call with no arguments. What happens when you call it? It will return a pointer to a float.
Operator precedence is always tricky, though. However, using parentheses can actually also be confusing because declaration follows use. At least, to me, intuitively arr2 looks like an array of 8 pointers to ints, but it is actually the other way around. Just takes some getting used to. Reason enough to always add a comment to these declarations, if you ask me :)
edit: example
By the way, I just stumbled across the following situation: a function that has a static matrix and that uses pointer arithmetic to see if the row pointer is out of bounds. Example:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NUM_ELEM(ar) (sizeof(ar) / sizeof((ar)[0]))
int *
put_off(const int newrow[2])
{
static int mymatrix[3][2];
static int (*rowp)[2] = mymatrix;
int (* const border)[] = mymatrix + NUM_ELEM(mymatrix);
memcpy(rowp, newrow, sizeof(*rowp));
rowp += 1;
if (rowp == border) {
rowp = mymatrix;
}
return *rowp;
}
int
main(int argc, char *argv[])
{
int i = 0;
int row[2] = {0, 1};
int *rout;
for (i = 0; i < 6; i++) {
row[0] = i;
row[1] += i;
rout = put_off(row);
printf("%d (%p): [%d, %d]\n", i, (void *) rout, rout[0], rout[1]);
}
return 0;
}
Output:
0 (0x804a02c): [0, 0]
1 (0x804a034): [0, 0]
2 (0x804a024): [0, 1]
3 (0x804a02c): [1, 2]
4 (0x804a034): [2, 4]
5 (0x804a024): [3, 7]
Note that the value of border never changes, so the compiler can optimize that away. This is different from what you might initially want to use: const int (*border)[3]: that declares border as a pointer to an array of 3 integers that will not change value as long as the variable exists. However, that pointer may be pointed to any other such array at any time. We want that kind of behaviour for the argument, instead (because this function does not change any of those integers). Declaration follows use.
(p.s.: feel free to improve this sample!)
typedef int (*PointerToIntArray)[];
typedef int *ArrayOfIntPointers[];
As a rule of thumb, right unary operators (like [], (), etc) take preference over left ones. So, int *(*ptr)()[]; would be a pointer that points to a function that returns an array of pointers to int (get the right operators as soon as you can as you get out of the parenthesis)
I think we can use the simple rule ..
example int * (*ptr)()[];
start from ptr
" ptr is a pointer to "
go towards right ..its ")" now go left its a "("
come out go right "()" so
" to a function which takes no arguments " go left "and returns a pointer " go right "to
an array" go left " of integers "
Here's an interesting website that explains how to read complex types in C:
http://www.unixwiz.net/techtips/reading-cdecl.html
Here's how I interpret it:
int *something[n];
Note on precedence: array subscript operator ([]) has higher priority than
dereference operator (*).
So, here we will apply the [] before *, making the statement equivalent to:
int *(something[i]);
Note on how a declaration makes sense: int num means num is an int, int *ptr or int (*ptr) means, (value at ptr) is
an int, which makes ptr a pointer to int.
This can be read as, (value of the (value at ith index of the something)) is an integer. So, (value at the ith index of something) is an (integer pointer), which makes the something an array of integer pointers.
In the second one,
int (*something)[n];
To make sense out of this statement, you must be familiar with this fact:
Note on pointer representation of array: somethingElse[i] is equivalent to *(somethingElse + i)
So, replacing somethingElse with (*something), we get *(*something + i), which is an integer as per declaration. So, (*something) given us an array, which makes something equivalent to (pointer to an array).
I guess the second declaration is confusing to many. Here's an easy way to understand it.
Lets have an array of integers, i.e. int B[8].
Let's also have a variable A which points to B. Now, value at A is B, i.e. (*A) == B. Hence A points to an array of integers. In your question, arr is similar to A.
Similarly, in int* (*C) [8], C is a pointer to an array of pointers to integer.
int *arr1[5]
In this declaration, arr1 is an array of 5 pointers to integers.
Reason: Square brackets have higher precedence over * (dereferncing operator).
And in this type, number of rows are fixed (5 here), but number of columns is variable.
int (*arr2)[5]
In this declaration, arr2 is a pointer to an integer array of 5 elements.
Reason: Here, () brackets have higher precedence than [].
And in this type, number of rows is variable, but the number of columns is fixed (5 here).
In pointer to an integer if pointer is incremented then it goes next integer.
in array of pointer if pointer is incremented it jumps to next array

Difference between int* array[] and int (*array)[] [duplicate]

What is the difference between the following declarations:
int* arr1[8];
int (*arr2)[8];
int *(arr3[8]);
What is the general rule for understanding more complex declarations?
int* arr[8]; // An array of int pointers.
int (*arr)[8]; // A pointer to an array of integers
The third one is same as the first.
The general rule is operator precedence. It can get even much more complex as function pointers come into the picture.
Use the cdecl program, as suggested by K&R.
$ cdecl
Type `help' or `?' for help
cdecl> explain int* arr1[8];
declare arr1 as array 8 of pointer to int
cdecl> explain int (*arr2)[8]
declare arr2 as pointer to array 8 of int
cdecl> explain int *(arr3[8])
declare arr3 as array 8 of pointer to int
cdecl>
It works the other way too.
cdecl> declare x as pointer to function(void) returning pointer to float
float *(*x)(void )
I don't know if it has an official name, but I call it the Right-Left Thingy(TM).
Start at the variable, then go right, and left, and right...and so on.
int* arr1[8];
arr1 is an array of 8 pointers to integers.
int (*arr2)[8];
arr2 is a pointer (the parenthesis block the right-left) to an array of 8 integers.
int *(arr3[8]);
arr3 is an array of 8 pointers to integers.
This should help you out with complex declarations.
int *a[4]; // Array of 4 pointers to int
int (*a)[4]; //a is a pointer to an integer array of size 4
int (*a[8])[5]; //a is an array of pointers to integer array of size 5
The answer for the last two can also be deducted from the golden rule in C:
Declaration follows use.
int (*arr2)[8];
What happens if you dereference arr2? You get an array of 8 integers.
int *(arr3[8]);
What happens if you take an element from arr3? You get a pointer to an integer.
This also helps when dealing with pointers to functions. To take sigjuice's example:
float *(*x)(void )
What happens when you dereference x? You get a function that you can call with no arguments. What happens when you call it? It will return a pointer to a float.
Operator precedence is always tricky, though. However, using parentheses can actually also be confusing because declaration follows use. At least, to me, intuitively arr2 looks like an array of 8 pointers to ints, but it is actually the other way around. Just takes some getting used to. Reason enough to always add a comment to these declarations, if you ask me :)
edit: example
By the way, I just stumbled across the following situation: a function that has a static matrix and that uses pointer arithmetic to see if the row pointer is out of bounds. Example:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NUM_ELEM(ar) (sizeof(ar) / sizeof((ar)[0]))
int *
put_off(const int newrow[2])
{
static int mymatrix[3][2];
static int (*rowp)[2] = mymatrix;
int (* const border)[] = mymatrix + NUM_ELEM(mymatrix);
memcpy(rowp, newrow, sizeof(*rowp));
rowp += 1;
if (rowp == border) {
rowp = mymatrix;
}
return *rowp;
}
int
main(int argc, char *argv[])
{
int i = 0;
int row[2] = {0, 1};
int *rout;
for (i = 0; i < 6; i++) {
row[0] = i;
row[1] += i;
rout = put_off(row);
printf("%d (%p): [%d, %d]\n", i, (void *) rout, rout[0], rout[1]);
}
return 0;
}
Output:
0 (0x804a02c): [0, 0]
1 (0x804a034): [0, 0]
2 (0x804a024): [0, 1]
3 (0x804a02c): [1, 2]
4 (0x804a034): [2, 4]
5 (0x804a024): [3, 7]
Note that the value of border never changes, so the compiler can optimize that away. This is different from what you might initially want to use: const int (*border)[3]: that declares border as a pointer to an array of 3 integers that will not change value as long as the variable exists. However, that pointer may be pointed to any other such array at any time. We want that kind of behaviour for the argument, instead (because this function does not change any of those integers). Declaration follows use.
(p.s.: feel free to improve this sample!)
typedef int (*PointerToIntArray)[];
typedef int *ArrayOfIntPointers[];
As a rule of thumb, right unary operators (like [], (), etc) take preference over left ones. So, int *(*ptr)()[]; would be a pointer that points to a function that returns an array of pointers to int (get the right operators as soon as you can as you get out of the parenthesis)
I think we can use the simple rule ..
example int * (*ptr)()[];
start from ptr
" ptr is a pointer to "
go towards right ..its ")" now go left its a "("
come out go right "()" so
" to a function which takes no arguments " go left "and returns a pointer " go right "to
an array" go left " of integers "
Here's an interesting website that explains how to read complex types in C:
http://www.unixwiz.net/techtips/reading-cdecl.html
Here's how I interpret it:
int *something[n];
Note on precedence: array subscript operator ([]) has higher priority than
dereference operator (*).
So, here we will apply the [] before *, making the statement equivalent to:
int *(something[i]);
Note on how a declaration makes sense: int num means num is an int, int *ptr or int (*ptr) means, (value at ptr) is
an int, which makes ptr a pointer to int.
This can be read as, (value of the (value at ith index of the something)) is an integer. So, (value at the ith index of something) is an (integer pointer), which makes the something an array of integer pointers.
In the second one,
int (*something)[n];
To make sense out of this statement, you must be familiar with this fact:
Note on pointer representation of array: somethingElse[i] is equivalent to *(somethingElse + i)
So, replacing somethingElse with (*something), we get *(*something + i), which is an integer as per declaration. So, (*something) given us an array, which makes something equivalent to (pointer to an array).
I guess the second declaration is confusing to many. Here's an easy way to understand it.
Lets have an array of integers, i.e. int B[8].
Let's also have a variable A which points to B. Now, value at A is B, i.e. (*A) == B. Hence A points to an array of integers. In your question, arr is similar to A.
Similarly, in int* (*C) [8], C is a pointer to an array of pointers to integer.
int *arr1[5]
In this declaration, arr1 is an array of 5 pointers to integers.
Reason: Square brackets have higher precedence over * (dereferncing operator).
And in this type, number of rows are fixed (5 here), but number of columns is variable.
int (*arr2)[5]
In this declaration, arr2 is a pointer to an integer array of 5 elements.
Reason: Here, () brackets have higher precedence than [].
And in this type, number of rows is variable, but the number of columns is fixed (5 here).
In pointer to an integer if pointer is incremented then it goes next integer.
in array of pointer if pointer is incremented it jumps to next array