I know that, for the following:
int a[10];
a is a pointer of the type int * to a[0], while &a is a pointer of type int (*)[10].
Now my question is for the following 2D array:
int b[20][30];
Is b a pointer of the type int **? Or is it a pointer of the type int (*)[30]?
Is &b a pointer of the type int (*)[20][30]?
Arrays are not pointers (this point cannot be stressed enough).
That being said, an array decays to a pointer to its first element. For example:
int a[10];
int b[20][30];
void print_a(int *);
void print_b(int (*)[30]);
print_a(a);
print_b(b);
The first element of a is a[0], and similarly the first element of b is b[0]. You basically take that first dimension away, and change it to a (*); I'll explain more in a moment since it is a bit more complex than that.
The relationship between pointers and arrays is riddled with contextual subtleties that aren't terribly difficult to grasp, but the size information in various scopes makes it interesting and also helps to give you an idea of how the decay works:
#include <stdio.h>
int h(int *pa)
{
printf("h(int *): sizeof pa=%zu\n", sizeof pa);
printf("h(int *): sizeof *pa=%zu\n", sizeof *pa);
return *pa;
}
int g(int (*pa)[5])
{
printf("g(int (*)[5]): sizeof pa=%zu\n", sizeof pa);
printf("g(int (*)[5]): sizeof *pa=%zu\n", sizeof *pa);
return h(*pa);
}
int f(int (*pa)[3][5])
{
printf("f(int (*)[3][5]): sizeof pa=%zu\n", sizeof pa);
printf("f(int (*)[3][5]): sizeof *pa=%zu\n", sizeof *pa);
return g(*pa);
}
int main(void)
{
int arr[2][3][5] = {{{11235}}};
printf("main: sizeof arr=%zu\n", sizeof arr);
printf("main: sizeof *arr=%zu\n", sizeof *arr);
printf("%d\n", f(arr));
}
Every pointer is the same size (this may not always be true on all platforms!), but by dereferencing the pointer, you see the size of a given element of the array, whether you dereference using the unary * operator or the [N] array notation, which is equivalent to *((array)+(N)) by definition.
Anyway, going back to the difference between pointers and arrays, you should understand that int[20][30] is not the same as int **. Why is that? Because of the fact that int[20][30] decays to a pointer of type int(*)[30], no more decay can occur until the pointer is dereferenced. Moreover, int ** is actually int *(*), which means it can point to the first element of an array of pointers. That is, int ** might have once been int *[N].
int foo[x][y][z] <=> int (*foo)[y][z]
int *foo[m][n] <=> int *(*foo)[n]
int (*foo[a])[b] <=> int (**foo)[b]
In the first case, we have a 3-D array, which decays to a pointer to a 2-D array; in other words, an array of arrays and a pointer to an array are closely related and interchangeable in many contexts aside from the size issue. The first dimension x is the one that decays, leaving the y and z dimensions.
In the second case, we have a 2-D array of pointers. This decays to a pointer to an array of pointers. Again, an array of arrays is closely related to a pointer to an array, and dimension m decays, leaving dimension n.
In the third case, we have an array of pointers to arrays. It decays to a pointer to a pointer to an array. Since dimension a is closest to the variable name, that is the one that decays, leaving dimension b. Note that since it is an array of pointers to arrays, the pointers could point to the first element of arrays themselves:
int arr[2][3][5];
int (*foo[2])[5] = { arr[0], arr[1] };
int (**foo_ptr)[5] = foo;
Recap:
Array (size A) of arrays (size B) <=> Pointer to array (size B)
Array (size A) of pointers <=> Pointer to pointer
The array that decays/grows is always the innermost array/pointer, the innermost being the one closest to the variable name in the variable declaration, with arrays having higher associativity than pointers, though of course parentheses make all the difference.
This rabbit hole obviously can be confusing, but I hope I helped a bit at least!
First of all make it clear that arrays are not pointers. Relationship between pointers and arrays is subtle. I would suggest you to read second chapter of tutorial on pointers by Ted Jensen first.
I would like to tell you something in a nutshell what has been describe in this chap. Consider following example.
int a[10];
int *p;
Now you can write
p=a;
that is equivalent to
p=&a[0];
This thing make many texts to say array is name of pointer. But it is better if you say "the name of the array is the address of first element in the array" .
Because though you can write
p=a;
but you can not write
a=p;
Now come to your question:
From above discussion it should be clear that b is not pointer of type int** .For example:
int b[10][10];
int **x;
int *p;
b=&p; // this is error
x=&p; // this fine
For your other questions you may use online CDECL.
if you write
int b[10][10]; --> declare b as array 10 of array 10 of int
int (*p)[10]; --> declare p as pointer to array 10 of int
int (*p)[10][20]; --> declare p as pointer to array 10 of array 20 of int
No, a is not of type int*, it is of type int [10] (i. e. of an array type). This is why sizeof(a) will give you the size of the array (40 bytes, assuming 32 bit integers).
Likewise, b is of type int [20][30], which is nothing other than an array of arrays. I. e. sizeof(b[0]) is the size of one line array, which is 120 in this case, the size of the entire array (sizeof(b)) is 20 times the size of the line arrays, which is 2400 bytes in this case.
The trick is, that an array decays into a pointer to its first element in almost all contexts. So when you do pointer arithmetic (as in b[3]) on the 2D array, b decays into a pointer of type int (*)[30], so the pointer arithmetic skips rows, adding three times the size of a row (360 bytes in this case) - the rows are the elements of the 2D array. The resulting type of b[3] is int [30], i. e. the dereferenced pointer.
Once you have dereferenced to a row array with b[3], you can again invoke pointer arithmetic to select the correct element in this row (b[3][5]). Again, the array-pointer-decay is invoked, the mechanic is the same.
Note that there is no pointer array involved as is the case when you emulate a 2D array with an int**. The double dereference b[3][5] translates into something like ((int*)b)[3*30 + 5] by virtue of array-pointer-decay, only the element itself is accessed from memory.
int* temp;
int arraySize = 20;
temp = (int *)malloc(arraySize * sizeof(int));
This will create a section in memory 20 "ints" long, similarly as you mentioned.
int** temp;
int arraySize = 20;
int rowSize = 10;
temp = (int **)malloc(arraySize * sizeof(int *));
for(i=0; i<arraySize; i++){
temp[i] = (int *)malloc(rowSize * sizeof(int));
}
That is what the 2D array would actually look like.
temp[0] would give you the address of the first "array". In which you could do something like above int *array = temp[0] then access it like a normal array but using *array[0] to get the value.
2D arrays really don't mesh well with pointers and saying *temp[0] to get the values of the first array. You can try to mess with it, you'll figure it out, but don't have a machine that can compile C with me right now.
Reference that may help: http://www.cs.swarthmore.edu/~newhall/unixhelp/C_arrays.html
Related
My teacher told me that int **array is not a 2D array, it is just a pointer to a pointer to an integer.
Now, in one of my projects I have to dynamically allocate a 2D array of structs, and this is how it is done:
struct cell **array2d = (struct x **)calloc(rows, sizeof(struct x *));
for (int i = 0; i < columns; i++) {
array2d[i] = (struct x *)calloc(j, sizeof(struct x));
}
But here we return a pointer to a pointer to the struct, so how is this a 2D array?
Before using dynamic allocation, I had a statically allocated array of the form:
array2d[][]
Now that I replaced it by dynamic allocation, I also replaced array2d[][] by **array2d.
Every function that takes array2d[i][j] als argument now returns an error saying the types don't match.
Could someone explain me what is happening here? What is the difference between **array and array[m][n] and why is the compiler complaining?
They're thoroughly different things.
An array is a sequence of values of the same type stored one after another in memory.
In C, an array is more or less interchangeable with a pointer to its first element — a[0] is *a,
a[1] is *(a+1), etc. — at least when we're talking about one-dimensional arrays.
But now consider:
int a[3][3];
in this case, a contains nine elements, contiguous in memory. a[0][0] through a[0][2], then a[1][0] immediately after, up until a[2][2].
If you pass a to a function, it would fit into a parameter type of int * or int[3][3] or int [][3] (knowing the "stride" of the second dimension is absolutely necessary to doing the math to look up a given element).
On the other hand:
int *b[3];
b[0] = malloc(...);
b[1] = malloc(...);
b[2] = malloc(...);
in this case, b is an array of 3 elements, each of which is a pointer to an array of 3 elements. You still access it like b[0]0] or b[1][2], but something completely different is happening under the hood. The elements aren't all stored contiguously in memory, and *b isn't any of them, it's a pointer. If we were to pass b to a function, we would receive it with a parameter of type int ** or int *[]. Knowing the length of each row in advance isn't necessary, and in fact each row could have a different length from the others. Some of the rows could even be null pointers, with no storage behind them for integers.
I've been learning C for about 2 months, still a novice:(
I know there are other similar questions on this site. I've read them, but still couldn't really understand, so here I am. Below is my code:
//naming my structure as ball
typedef struct ball_room {
int enter;
int exit;
} ball;
//I've omitted some irrelevant details for brevity
int i, n, max;
scanf("%d", &n);
ball person[n];
.../*assign values to ball.enter and ball.exit with user input*/
max = 1;
for (i = 0; i < n; i++)
if (ball_room(person, person[i].enter, n) > max)
max = ball_room(person, person[i].enter, n);
printf("%d\n", max);
return 0;
}
and below is my function receiving the array:
//This function returns the number of people in the ballroom
//when b[j](person[j] in "main") enters
int ball_room(ball *b, int i, int n)
{
int people = 0, j;
for (j = 0; j < n; j++)
if (b[j].enter <= i && b[j].exit > i)
people++;
return people;
}
my question is that why is it b[j].enter instead of b[j]->enter, which my compiler wouldn't accept?
In my limited experience, when manipulating structure itself (the object), I use . to go inside the structure, and when it's a pointer (the address), I use -> (hope this is correct.)
And in this case, I pass the array to function using ball *b, which represent the address of person[0], so I can access the whole array. But shouldn't ball *b be in the form of a pointer and therefore I should use -> to access its content? It's just an address that I pass to the function.
This is my first time doing something with an array of structures, please help me get this clear, thank you!
Given ball *b, b[j] is an element from the elements that b points to. Thus b[j] is not a pointer; it is a struct. Since it is a struct, you use . to refer to members in it.
The definition of b[j] in the C standard is that it is *((b)+(j)). So it takes the pointer b, moves j elements beyond it, and then applies *.
Since * is already applied in b[j], you do not need ->, just ..
you use . instead of -> because of this declaration of parameters:
int ball_room(ball *b, int i, int n)
b is expected to be pointer to data with type ball, so you can access it in various ways:
array way: e.g. b[5].somefield = 15 - you use dot here, because if b is of type ball *, it means that b is pointer OR it is array of objects with type b, if it's array of objects with type b (which is your case) you use . to access fields of object
pointer way: e.g. (b+5)->somefield = 15 - it will do exactly same thing as code above, but you will access data in pointer way
In C/C++ an array devolves into the address of it's first member. So when you pass the array to ball_room what actually gets passed is &ball[0].
Now inside ball_room the reverse happens. b is a pointer to ball. But here you use it as an array b[j]. So it un-devolves back into an array of structs. So what b[j] gives you is the struct and not a pointer to a struct. Consequently you access it using . instead of ->.
You can also use (b + j)->somefield. Or for even more fun how about writing j[b].somefield. The later being a really confusing left-over from the eraly compiler days when a[b] truly got turned into *(a + b) internally.
For explanation of the current issue, see Eric's answer; in some of the answers given so far there is dangerous wording applied, so just to make clear: When do we have an array and when a pointer???
Consider the following:
int a[7];
As long as we can refer to a directly, we still have an array and can use any operations that are valid on, e. g. getting size:
size_t n = sizeof(a); // size in bytes, not ints, i. e. 7*sizeof(int)
You can pass arrays to functions or even do pointer arithmetics on:
f(a);
a + 1;
In both cases, the array "decays" to a pointer, though, and the result is a pointer as well. Be aware that you can assign new values to a pointer, but not to an array itself (you can assign new values to the array's elements, directly or via pointer), so you cannot do things like ++a either.
When an array decays to a pointer, it gets a pointer to its first element:
int* ptr = a;
int* ptr = &*a; // only pointers can be dereferenced -> a decays!
int* ptr = &a[0]; // short for &*(a + 0)...
All result in exactly the same; however, the following is invalid:
int* ptr = &a;
Taking the address of an entire array actually is possible, but the resulting pointer is not of type "pointer to element" nor of type "pointer to pointer to element" (int** in the example), but of type "pointer to array of specific size". Syntax for is ugly, though, but the following would be legal again:
int(*aptr)[7] = &a;
You need to read: if I dereference ptr, I get int[7]...
Once decayed, there is only a pointer to the array left (more precisely: to one of the array elements, directly after decaying, to the first; array and first element always share the same address, so, although of different type, both pointers ptr and aptr from above hold exactly the same value). Pointers can be moved around within the array, but they do not hold as much information as the array itself, especially, the array size gets lost. This is why one needs to pass the array's length together with the pointer to functions (if needed; another variant is a sentinel value denoting the array end such as the terminating null character in strings or the null pointer following the string arguments in main's arguments list):
int a[7];
f(a, sizeof(a)/sizeof(*a)); // division: sizeof is in bytes, dividing by size
// of first element gives number of elements
Possibly with f as:
void f(int b[], size_t n)
// ^^^^^^^ in function parameter lists, just alternative syntax for int* b !!!
// however, we can show more explicitly that we expect a pointer
// to an array this way...
{
size_t m = sizeof(b); // as b is a POINTER, gives the constant (but hardware specific!)
// size of a pointer (on typical modern 64-bit hardware 8 bytes),
// no matter what size of the array being pointed to is!!!
while(n)
{
*b++ = n--;
// ^^ advances pointer, NOT array!
}
}
Hope this helps to avoid confusion.
In C, the array name is a pointer to array’s first element, hence your function declaration has name ball *band works when you pass a ball[] instance.
Try dynamically allocating the memory by using malloc() and passing that pointer to your function.
I started learning C recently, and I'm having a problem understanding pointer syntax, for example when I write the following line:
int ** arr = NULL;
How can I know if:
arr is a pointer to a pointer of an integer
arr is a pointer to an array of pointers to integers
arr is a pointer to an array of pointers to arrays of integers
Isn't it all the same with int ** ?
Another question for the same problem:
If I have a function that receives char ** s as a parameter, I want to refer to it as a pointer to an array of strings, meaning a pointer to an array of pointers to an array of chars, but is it also a pointer to a pointer to a char?
Isn't it all the same with int **?
You've just discovered what may be considered a flaw in the type system. Every option you specified can be true. It's essentially derived from a flat view of a programs memory, where a single address can be used to reference various logical memory layouts.
The way C programmers have been dealing with this since C's inception, is by putting a convention in place. Such as demanding size parameter(s) for functions that accept such pointers, and documenting their assumptions about the memory layout. Or demanding that arrays be terminated with a special value, thus allowing "jagged" buffers of pointers to buffers.
I feel a certain amount of clarification is in order. As you'd see when consulting the other very good answers here, arrays are most definitely not pointers. They do however decay into ones in enough contexts to warrant a decades long error in teaching about them (but I digress).
What I originally wrote refers to code as follows:
void func(int **p_buff)
{
}
//...
int a = 0, *pa = &a;
func(&pa);
//...
int a[3][10];
int *a_pts[3] = { a[0], a[1], a[2] };
func(a_pts);
//...
int **a = malloc(10 * sizeof *a);
for(int i = 0; i < 10; ++i)
a[i] = malloc(i * sizeof *a[i]);
func(a);
Assume func and each code snippet is compiled in a separate translation unit. Each example (barring any typos by me) is valid C. The arrays will decay into a "pointer-to-a-pointer" when passed as arguments. How is the definition of func to know what exactly it was passed from the type of its parameter alone!? The answer is that it cannot. The static type of p_buff is int**, but it still allows func to indirectly access (parts of) objects with vastly different effective types.
The declaration int **arr says: "declare arr as a pointer to a pointer to an integer". It (if valid) points to a single pointer that points (if valid) to a single integer object. As it is possible to use pointer arithmetic with either level of indirection (i.e. *arr is the same as arr[0] and **arr is the same as arr[0][0]) , the object can be used for accessing any of the 3 from your question (that is, for second, access an array of pointers to integers, and for third, access an array of pointers to first elements of integer arrays), provided that the pointers point to the first elements of the arrays...
Yet, arr is still declared as a pointer to a single pointer to a single integer object. It is also possible to declare a pointer to an array of defined dimensions. Here a is declared as a pointer to 10-element array of pointers to arrays of 10 integers:
cdecl> declare a as pointer to array 10 of pointer to array 10 of int;
int (*(*a)[10])[10]
In practice array pointers are most used for passing in multidimensional arrays of constant dimensions into functions, and for passing in variable-length arrays. The syntax to declare a variable as a pointer to an array is seldom seen, as whenever they're passed into a function, it is somewhat easier to use parameters of type "array of undefined size" instead, so instead of declaring
void func(int (*a)[10]);
one could use
void func(int a[][10])
to pass in a a multidimensional array of arrays of 10 integers. Alternatively, a typedef can be used to lessen the headache.
How can I know if :
arr is a pointer to a pointer of an integer
It is always a pointer to pointer to integer.
arr is a pointer to an array of pointers to integers
arr is a pointer to an array of pointers to arrays of integers
It can never be that. A pointer to an array of pointers to integers would be declared like this:
int* (*arr)[n]
It sounds as if you have been tricked to use int** by poor teachers/books/tutorials. It is almost always incorrect practice, as explained here and here and (
with detailed explanation about array pointers) here.
EDIT
Finally got around to writing a detailed post explaining what arrays are, what look-up tables are, why the latter are bad and what you should use instead: Correctly allocating multi-dimensional arrays.
Having solely the declaration of the variable, you cannot distinguish the three cases. One can still discuss if one should not use something like int *x[10] to express an array of 10 pointers to ints or something else; but int **x can - due to pointer arithmetics, be used in the three different ways, each way assuming a different memory layout with the (good) chance to make the wrong assumption.
Consider the following example, where an int ** is used in three different ways, i.e. p2p2i_v1 as a pointer to a pointer to a (single) int, p2p2i_v2 as a pointer to an array of pointers to int, and p2p2i_v3 as a pointer to a pointer to an array of ints. Note that you cannot distinguish these three meanings solely by the type, which is int** for all three. But with different initialisations, accessing each of them in the wrong way yields something unpredictable, except accessing the very first elements:
int i1=1,i2=2,i3=3,i4=4;
int *p2i = &i1;
int **p2p2i_v1 = &p2i; // pointer to a pointer to a single int
int *arrayOfp2i[4] = { &i1, &i2, &i3, &i4 };
int **p2p2i_v2 = arrayOfp2i; // pointer to an array of pointers to int
int arrayOfI[4] = { 5,6,7,8 };
int *p2arrayOfi = arrayOfI;
int **p2p2i_v3 = &p2arrayOfi; // pointer to a pointer to an array of ints
// assuming a pointer to a pointer to a single int:
int derefi1_v1 = *p2p2i_v1[0]; // correct; yields 1
int derefi1_v2 = *p2p2i_v2[0]; // correct; yields 1
int derefi1_v3 = *p2p2i_v3[0]; // correct; yields 5
// assuming a pointer to an array of pointers to int's
int derefi1_v1_at1 = *p2p2i_v1[1]; // incorrect, yields ? or seg fault
int derefi1_v2_at1 = *p2p2i_v2[1]; // correct; yields 2
int derefi1_v3_at1 = *p2p2i_v3[1]; // incorrect, yields ? or seg fault
// assuming a pointer to an array of pointers to an array of int's
int derefarray_at1_v1 = (*p2p2i_v1)[1]; // incorrect; yields ? or seg fault;
int derefarray_at1_v2 = (*p2p2i_v2)[1]; // incorrect; yields ? or seg fault;
int derefarray_at1_v3 = (*p2p2i_v3)[1]; // correct; yields 6;
How can I know if :
arr is a pointer to a pointer of an integer
arr is a pointer to an array of pointers to integers
arr is a pointer to an array of pointers to arrays of integers
You cannot. It can be any of those. What it ends up being depends on how you allocate / use it.
So if you write code using these, document what you're doing with them, pass size parameters to the functions using them, and generally be sure about what you allocated before using it.
Pointers do not keep the information whether they point to a single object or an object that is an element of an array. Moreover for the pointer arithmetic single objects are considered like arrays consisting from one element.
Consider these declarations
int a;
int a1[1];
int a2[10];
int *p;
p = &a;
//...
p = a1;
//...
p = a2;
In this example the pointer p deals with addresses. It does not know whether the address it stores points to a single object like a or to the first element of the array a1 that has only one element or to the first element of the array a2 that has ten elements.
The type of
int ** arr;
only have one valid interpretation. It is:
arr is a pointer to a pointer to an integer
If you have no more information than the declaration above, that is all you can know about it, i.e. if arr is probably initialized, it points to another pointer, which - if probably initialized - points to an integer.
Assuming proper initialization, the only guaranteed valid way to use it is:
**arr = 42;
int a = **arr;
However, C allows you to use it in multiple ways.
• arr can be used as a pointer to a pointer to an integer (i.e. the basic case)
int a = **arr;
• arr can be used as a pointer to a pointer to an an array of integer
int a = (*arr)[4];
• arr can be used as a pointer to an array of pointers to integers
int a = *(arr[4]);
• arr can be used as a pointer to an array of pointers to arrays of integers
int a = arr[4][4];
In the last three cases it may look as if you have an array. However, the type is not an array. The type is always just a pointer to a pointer to an integer - the dereferencing is pointer arithmetic. It is nothing like a 2D array.
To know which is valid for the program at hand, you need to look at the code initializing arr.
Update
For the updated part of the question:
If you have:
void foo(char** x) { .... };
the only thing that you know for sure is that **x will give a char and *x will give you a char pointer (in both cases proper initialization of x is assumed).
If you want to use x in another way, e.g. x[2] to get the third char pointer, it requires that the caller has initialized x so that it points to a memory area that has at least 3 consecutive char pointers. This can be described as a contract for calling foo.
C syntax is logical. As an asterisk before the identifier in the declaration means pointer to the type of the variable, two asterisks mean pointer to a pointer to the type of the variable.
In this case arr is a pointer to a pointer to integer.
There are several usages of double pointers. For instance you could represent a matrix with a pointer to a vector of pointers. Each pointer in this vector points to the row of the matrix itself.
One can also create a two dimensional array using it,like this
int **arr=(int**)malloc(row*(sizeof(int*)));
for(i=0;i<row;i++) {
*(arr+i)=(int*)malloc(sizeof(int)*col); //You can use this also. Meaning of both is same. //
arr[i]=(int*)malloc(sizeof(int)*col); }
There is one trick when using pointers, read it from right hand side to the left hand side:
int** arr = NULL;
What do you get: arr, *, *, int, so array is a pointer to a pointer to an integer.
And int **arr; is the same as int** arr;.
int ** arr = NULL;
It's tell the compiler, arr is a double pointer of an integer and assigned NULL value.
There are already good answers here, but I want to mention my "goto" site for complicated declarations: http://cdecl.org/
Visit the site, paste your declaration and it will translate it to English.
For int ** arr;, it says declare arr as pointer to pointer to int.
The site also shows examples. Test yourself on them, then hover your cursor to see the answer.
(double (^)(int , long long ))foo
cast foo into block(int, long long) returning double
int (*(*foo)(void ))[3]
declare foo as pointer to function (void) returning pointer to array 3 of int
It will also translate English into C declarations, which is prety neat - if you get the description correct.
I know, that static arrays are laid out contiguously in memory.
So, for example, int T[10][10] is basically stored the same way as int T[100].
I can access element of index i, j many ways, for example:
int T[10][10];
/*filling array*/
int i=3, j=7;
int x = T[i][j];
//EDIT - old and wrong: int * ptr = T;
int * ptr = &T[0][0];
int y = *(ptr + 10* i + j);
On the other hand, when I create dynamicaly allocated 2-dimensional array by myself:
int ** T;
T = malloc(10 * sizeof(int *));
for(i = 0; i < N; i++)
T[i] = malloc(10 * sizeof(int));
My array contains pointers to
It is obvious, that I can access element of this array by:
int i=3, j=7;
int x = *(*(T+i)+j);
And now my question: why and how does it work for static arrays?
Why does
int T[10][10];
/*filling array*/
int i=3, j=7;
int x = *(*(T+i)+j);
return good value to x, when this table doesn't contain pointers to arrays? *(*(T+i)) shouldn't have sense there in my opinion, end even if, it should return T[0][i], as T points at the first element of array. How does compiler interpret this, is * something other than dereference here? Enlighten me.
For starters:
int * ptr = T;
That's not going to actually work, at least without your compiler yelling at you. Very loudly. The correct way to do this is:
int * ptr = &t[0][0];
This point is actually very relevant to your question.
As you know, when used in an expression, an array gets decayed to a pointer. For example:
char foo[10];
bar(foo);
When used in an expression, like a parameter to a function, the array decays to a pointer to the underlying type. foo gets you a char *, here.
However, and this is the key point: the array only decays one level. If the array is a two-dimensional array, the array does not get decayed to the underlying value, an int in this case. The two dimensional array reference decays to a pointer to a one-dimensional array:
int T[10][10];
/*filling array*/
int i=3, j=7;
int x = *(*(T+i)+j);
The sequence of steps that occurs here:
T decays to a pointer to an array of 10 integers, or int (*)[10]
The addition of i advances the pointer by the given value. The pointer is advanced by the size of the element being pointed to. Since the pointer points to array of 10 integers, the pointer is advanced accordingly. If i was 2, the pointer is advanced by "two arrays of 10 integers", loosely speaking.
The * operator takes a "pointer to an array of 10 integers" and gives you "an array of 10 integers" as a result. In other words: from int (*)[10] to int [10].
Since the result is used in an expression, namely the left operand of + j, and the left operand is an array type, the array type decays to a "pointer to int".
j is added to the result, and dereferenced.
Why does
int T[10][10];
/*filling array*/
int i=3, j=7;
int x = *(*(T+i)+j);
return good value to x
The magic is all in *(*(T+3)+7) (I have converted to the literal values).
T is an array (of size 10) of arrays (of size 10) of int.
When T is used in an an expression it decays into a pointer to its first element, so it decays to "pointer to arrays (of size 10) of int".
Adding an integer to that pointer will advance to the fourth element of the array.
So T+3 is a pointer to an array of 10 ints, and specifically the fourth such array in T.
*(T+3) indirects through that pointer to give an l-value of type "array of 10 ints".
Ah-ha! That is another array being used in an expression - so it decays into a pointer to it's first element! (It wouldn't decay in sizeof, so sizeof(*(T+3)) would be typically 40.)
(*(T+3) + 7) just points at the eight element in the array, and ...
*(*(T+3) + 7) is an l-value of type int!
I have an array of int pointers int* arr[MAX]; and I want to store its address in another variable. How do I define a pointer to an array of pointers? i.e.:
int* arr[MAX];
int (what here?) val = &arr;
The correct answer is:
int* arr[MAX];
int* (*pArr)[MAX] = &arr;
Or just:
int* arr [MAX];
typedef int* arr_t[MAX];
arr_t* pArr = &arr;
The last part reads as "pArr is a pointer to array of MAX elements of type pointer to int".
In C the size of array is stored in the type, not in the value. If you want this pointer to correctly handle pointer arithmetic on the arrays (in case you'd want to make a 2-D array out of those and use this pointer to iterate over it), you - often unfortunately - need to have the array size embedded in the pointer type.
Luckily, since C99 and VLAs (maybe even earlier than C99?) MAX can be specified in run-time, not compile time.
Should just be:
int* array[SIZE];
int** val = array;
There's no need to use an address-of operator on array since arrays decay into implicit pointers on the right-hand side of the assignment operator.
IIRC, arrays are implicitly convertible to pointers, so it would be:
int ** val = arr;
According to this source http://unixwiz.net/techtips/reading-cdecl.html, by using the "go right when you can, go left when you must" rule, we get the following 2 meanings of the declarations given in the previous answers -
int **val ==> val is a pointer to pointer to int
int* (*pArr)[MAX] ==> pArr is a pointer to an array of MAX length pointers to int.
I hope the above meanings make sense and if they don't, it would probably be a good idea to peruse the above mentioned source.
Now it should be clear that the second declaration is the one which moteutsch is looking for as it declares a pointer to an array of pointers.
So why does the first one also work? Remember that
int* arr[MAX]
is an array of integer pointers. So, val is a pointer to, the pointer to the first int declared inside the int pointer array.
#define SIZE 10
int *(*yy)[SIZE];//yy is a pointer to an array of SIZE number of int pointers
and so initialize yy to array as below -
int *y[SIZE]; //y is array of SIZE number of int pointers
yy = y; // Initialize
//or yy = &y; //Initialize
I believe the answer is simply:
int **val;
val = arr;
As far as I know there is no specific type "array of integers" in c, thus it's impossible to have a specific pointer to it. The only thing you can do is to use a pointer to the int: int*, but you should take into account a size of int and your array length.