I know that if arr is an array then arr[i]=*(arr+i); and if is a 2D array then arr[i][j]=*(*(arr+i)+j); So I have this code
main(){
int arr[5][5];
int arr2[25]; // same as arr[5][5];
int i,j;
for(i=0;i<5;i++)
for(j=0;j<5;j++){
arr[i][j]=i+j;
printf("arr[%d][%d] is at %p\n",i,j,&arr[i][j]);
}
printf("*(arr+i)=%d\n",*(arr+1)); // why this dont work
for(i=0;i<24;i++){
arr2[i]=i;
printf("arr2[%d] is at %p\n",i,(arr2+i));
}
printf("*(arr+i)=%d\n",*(arr2+1)); // prints 1 as expected
}
I know that in C there's no such thing as 2D array, its basically a linear row major contiguous blob of memory. So I'm wondering why I cant print the value of 2D arr using *(arr+1), which means add 1*5*4 bytes to the base of arr and dereference the value at that address. I know that **(arr+1) works but I dont know why I need that extra asterix ? Also If I do this printf("*(arr+i)=%p\n",*(arr+1)); is the same as I would use (arr+i) to interpret as an address
arr is an array of arrays of ints. Its type is int [5][5]. So, the elements of arr is 1D arrays. When used in expression, in most cases, arrays converted to a pointer to its first element. In *(arr + 1), arr is converted to pointer to arr[0], i.e, first 1D array. Adding 1 will increment it by 5*4 = 20 bytes, i.e, next element of array arr which is arr[1].
Since arr[1] is an array, it can't be printed (as a whole), but its address can be. arr[1] is itself an array and it will decay to pointer to its first element, i.e, arr[1][0]. To print its element you need another dereference which is acheived by arr[1][j] (j is columns).
arr[1][j] is equivalent to *(arr[1] + j) which is ultimately equivalent to *(*(arr + 1) + j).
Suggested Reading: What exactly is the array name in c?
As you said, a 2D array in C is basically an array of 1D arrays. You might think of this as an array of rows.
The rightmost * will dereference the outer array, selecting the row you want.
*(arr+i) //this gives me a pointer to the row I want
The * to the left of that will dereference in the inner array, selecting an element from the row.
*(*(arr+i)+j) //this gives me an element in the row
**(arr+i) is just a special case of the above where the column number j is 0.
The type of *(arr+1) = the type of arr[1] = int [5], which will decay to int* when used in printf.
To print the pointer, use:
printf("*(arr+i)=%p\n", *(arr+1));
To print the object it points to, use:
printf("*(*(arr+i))=%d\n", *(*(arr+1)));
You can make your code easier to read by using:
printf("arr[1] = %p\n", arr[1]); // Print the pointer
printf("arr[1][0] = %d\n", arr[1][0]); // Print the value
Related
After reading some posts on this site, I realized that array in C isn't just a constant pointer as I originaly thought, but is itself a distinct type, but in most cases array "decays" to a constant pointer to the first element of the array. Because of this new information, a question arised in my mind. Suppose we have a two-dimensional A[10][10]. Why is the result of the expression *A a pointer to the first element of the array ? I thought that in this expression, A decays to a constant pointer to the first element of the array A[0][0], and then the application of the indirection should give us the value of the A[0][0], but in fact it still gives us the address of the first element of the array. Certainly, something is wrong with my logic or my understanding of the arrays or pointers, so where do I get it wrong ?
Thanks in advance.
The first element of A is A[0], not A[0][0].
This is because A is an array of ten things. C does not have two-dimensional arrays as a primary type. An array with multiple dimensions is derived or constructed as multiple layers of arrays. To the compiler, the resulting type is still just an array, whose elements happen to be further arrays.
Thus, in *A:
A is converted to a pointer to its first element. That pointer is &A[0], so *A becomes *&A[0].
* and & cancel, so the expression becomes A[0].
A[0] is an array of ten elements, so it is converted to a pointer to its first element, &A[0][0].
*A, or A[0], is itself an array of 10 elements and and array is always expressed by a pointer to its first element. However A[10][10] (let's say an array of ints) is effectively a block of memory holding 100 ints, the 10 of the first row followed by the 10 of the second row and so on. But if the expression *A or A[0] would return an int instead of a ptr to that row, it would be impossible to use the expression A[0][0], right ?
However, because such multidimensional array is a single block of memory, it's also possible to cast it to a pointer and then access it with an expression of this kind :
((int *)A)[iRow * 10 + iCol];
Which is equivalent to the expression :
A[iRow][iCol];
But this if it's possible for a 2D array declared this way :
int main()
{
int A[10][10] = { 0 };
A[9][9] = 9999;
printf("==> %d\n", ((int *)A)[9 * 10 + 9]); //==> 9999
return 0;
}
It is not if the memory is potentially made of separate blocks of bytes (probably requiring several calls to malloc) as with this kind of expressions :
int * A[10]; // or
int ** A;
A decays to a constant pointer to the first element of the array
A[0][0]
No, it does not. Why?
C standard specifies that *(pointer + integer) == pointer[integer] so the *A is an equivalent of *(A + 0) which is A[0]. A[0] will not give you the element A[0][0] only the single dimensional array which will decay to pointer to the first element of the first row of this array.
#include<stdio.h>
int test(int *x);
void main(){
int arr[2][3], a;
arr[1][2] = 2;
printf("%d\n", test((int *)arr));
printf("%d\n", *(*(arr+1)+2));
}
int test(int *prr){
int a;
a = *(*(prr+1)+2);
return a;
}
The above code is giving me the following error:
error: invalid type argument of unary β*β (have βintβ)
a = *( *(prr+1)+2);
^
but the same declaration works in the main function:
printf("%d\n", *( *(arr+1)+2)).
Also when I replace it with *((arr+1*3) + 2), 3 being the size of 2nd dimension, in the function test, it worked and I could not understand how ??? I really want to know the reason. please help!!!
And why is their a need to type cast a 2D array, but not 1D array when passing to a function.
I used the help of http://www.geeksforgeeks.org/pass-2d-array-parameter-c/, but the reason was not there.
In main function arr is an array of arrays of int. *(*(arr+1)+2) is equivalent to *(arr[1] + 2) = arr[1][2]. arr[1] is an array and will decay to pointer to first element arr[1][0].
In test, prr is a pointer to int. *(prr+1)+2 is equivalent to *(prr[1] + 2). prr[1] is an int. This makes the expression prr[1] + 2 an int. Operand of unary * operator must be a pointer variable.
Change function prototype to
int test(int x[][3]);
and make function call as
printf("%d\n", test(arr));
in function test(int *prr) prr points to a integer not a array.
so *(Prr+1) is a integer, but '*' unary operator is only applied to pointers.
Okay, a quick short lesson on arrays and pointers.
Thumb rule 1: Arrays and pointers are almost always interchangable but there are exceptions!
Taking a 1-D array, we can declare it like this :-
int arr[10];
This declares a variable named arr which can hold 10 integer elements.
I can similarly use the pointer notation to represent this array using a pointer variable or by using the array name (arr) itself.
printf ("%d", arr[2]); // Array method : will print out the third element, indexing starts from 0
Thumb rule 2: Array name(be it 1D 2D 3D 4D) always decays into a pointer or an address.
printf ("%lu", arr) //will print out the base address of the array, i.e address of the first element
How to print the value using a pointer ? Simply, dereference it using * operator.
printf("%d", *arr) //Pointer notation - will print the first value
How to reference the array using another variable?
int *ptr = arr; //Pointer notation - just simply write the array name as it decays into an address
printf("%d", *ptr); //Pointer notation - prints the first element
Many people say int *ptr is pointer to an array.
In reality it's not. It's actually a pointer to an integer not an array. Why?
Because in the first place we are storing the address of the first integer of the array and then we can traverse it by incrementing the pointer. So, in real pointer is storing the address of an integer(First integer).
Now, coming to 2D arrays :-
Declaration:-
int arr[2][3]; // arrays of 2 rows and 3 columns, total 6 elements
Same above rules implies :-
printf("%d", arr[0][1]); //prints the second element of the first row.
printf("%lu", arr) //prints the base address of the 2D array
Coming to Pointer Notation :-
printf("%d", *(*(arr + 0) + 1); // how this works?
arr contains the address. Adding a integer to it with make you jump to that row.
arr + 1 // gives the second row, i.e. arr is currently pointing to the first element of second row.
Now, further adding an integer to it, will make you skip to that specified column in that particular row.
((arr + 1) // second row + 2 ) // will you skip to third element of the second row
This is the implicit pointer notation that language gives you, when you choose to treat the array name as a pointer.
Now coming to your problem : - Explicit Pointer Notation:-
What are you trying to achieve is, storing the base address of the 2D array in a pointer.
How to correctly do that ?
int (*ptr)[3]; //reading it goes like this - ptr is a pointer to a 1D array of 3 ints
The 3 here specifies the number of columns your 2D array has.
So what it is doing is, trying to store the base address of first 1D array of that 2D array (which means 0th row base address) into the pointer.
The rest remains the same.
int (*ptr)[3] = arr; // storing the 2D array in ptr
Now, you can use it as a normal pointer(Pointer notation applies on it)
(ptr + 1) //now ptr is pointer to the Second 1D array of that 2D array or you can say to the second row's first element.
Another way you can catch an array in a function is like this:-
I use it very less though.
int main()
{
int arr[2][2];
fun(arr);
}
void fun(int catch[][])
{
}
// This is simple to understand and as well as to relate. Now, again catch can be used as pointer or as an array. It depends on you :)
void fun1(int (*ptr)[2])
{
//my way
printf("%d", ptr[1][1]);
printf("%d", *(*(ptr + 1) + 1));
//answer will be the same
}
//Ptr now contains that 2D array base address, again can be used as an array or a pointer :)
In you function main arr is a 2-d array of int and thus, this works -
printf("%d\n", *(*(arr+1)+2)); // you dereference it twice to get value
But in your function test, parameter is of type int * and therefore , this expression -
a = *( *(prr+1)+2); // prr is of type int *
gives error as you try to dereference int * twice. There is only one level of indirection , so you need to dereference once. Also, you could achieve same by passing 2-d array directly without cast and it would work.
Something like this -
int test(int **prr){
// you code
}
and in main you can call it like this -
int x = test(arr);
Here is the question:
What is the output of the program?
#include<stdio.h>
int main()
{
int A[2][10]={{1,2,3,4,5,6,7,8,9,10},{11,12,13,14,15,16,17,18,19,20} };
int (*v)[10]=A;
printf("**v=%d\n",**v);
printf("**(v+1)=%d\n",**(v+1));
printf("*(*v+1)=%d\n",*(*v+1));
printf("*(v[0]+1)=%d\n",*(v[0]+1));
printf("*(v[1])=%d\n",*(v[1]));
}
Outputs:
**v=1
**(v+1)=11
*(*v+1)=2
*(v[0]+1)=2
*(v[1])=11
Especially, I'm not very clear about how did *v divide array A into 10 parts, and please tell me the reasons about each output.
Thanks!
There's a concept called array decay at work. Also, pass each definition through cdecl.
The second line is
declare v as pointer to array 10 of int
Thus it is a pointer to an array of 10 elements. This pointer is initialized with A -- the array it points to is the first row of A.
Then, v+1 is another pointer to an array of 10 elements, following the first one. Thus, it is the second row of A.
In the **v, *v will be replaced by value of v[0], which is an address, say X, therefore the outer * will be used to indicate the value of address X, which is 1.
In the **(v+1), *(v+1) will become v[1], which is again an address, say Y, and the outer asterisk will give the value at address Y, which is 11.
*(*v+1)=2 => *(v[0] + 1) => here pointer shifts to the next location, and this location is v[0][1], which is similar to *(*(v+0)+1). Value at v[0][1] is 2.
*(v[0]+1)=2, same reason.
*(v[1])=11, v[1] holds the base address of the second row, which is the starting address of second row's 0th column, and the value at that location is 11.
Okay, let's review first, how arrays decay and second, how declarations work.
A is declared as a 2D array. When A is used in any expression, it will "decay" to a pointer to its first element. In C, a 2D array is made up of two 1D arrays. So an element of a 2D array is a 1D array. So when A is used in any expression, it will decay to a pointer to the first row of A, which is an array of 10 ints.
int (*v) [10] means that v is a pointer to an array of 10 ints. The assignment
int (*v)[10] = A;
is an expression, so A there has decayed to a pointer to 10 ints as well, so the assignment is valid.
So now when you look at **v, you are dereferencing first, v, which means you are getting what v points at, which is the first row of your 2D array. Then you are dereferencing *v, which means you are getting the first element of that first row. That is 1, so your output is 1.
When you look at **(v + 1), you are first adding 1 to the pointer v. Since v points to a row, adding 1 gets you a pointer to the next row. Then you do the double dereferencing as above and you get the first element of the next row, which is 11.
When you look at *(*v + 1), you are first dereferencing v, which means you get the first row. Then you add 1 to that, which gets you a pointer to the next element of the row. Then you dereference that, which gets you the 2, the second element.
To summarize: v points to the whole first row. *v points to the first element of the first row. (v + 1) points to the whole second row. (*v + 1) points to the second element of the first row.
After this, figuring out the rest is probably quite easy.
Does name of a 2D array give its base address in C like in 1D array? And how can i store the base address of a 2d array in a pointer variable?
It decays to a pointer to the first element:
int a[5][7];
decays to
int (*pa)[7] = a;
In practice, the value stored in pa will be the same as that of a pointer to the first int element of a, but the correct way to get a pointer to the first element of a is to use
int *p_elm = &(a[0][0]);
or equivalently
int *p_elm = &(pa[0][0]);
However, note that a pointer to the first element can't (strictly) be treated as a pointer to the beginning of a N*M array; see e.g. http://www.lysator.liu.se/c/c-faq/c-2.html#2-11
A 2D array is essentially a 1D array, where each element itself is an array.
The name of the array is equivalent to &arrayName[0].
Assigning a pointer to this address is same as always, something like:
int myArray[5][5];
int (*arrayptr)[5] = myArray;
This says arrayptr is a pointer to an array of 5 integers. Since myArray is an address to the first element, which is an int[5], our declaration is fine.
When you dereference this pointer however, you're going to get the first element, which is an array. Therefore you can do something like:
(*arrayptr)[3]; // parens necessary for precedence issues
to access the 3rd element in the array nested inside the first element of the "outer array".
It is the equivalent of
myArray[0][3];
What's happening is you're dereferencing arrayptr which will yield a 1D array (of size 5 in this case).. then you're asking for the 4th element of this 1D array.
Now, if what you're looking for is the top-left "corner" of the matrix, you will want:
int *topleft = &(myArray[0][0]);
Yes and you the store the address as:
int *p = &a[0][0];
Use the address of operator to point to the offset of base.
char base[2][2];
int *basepointer = &base;
I would like to give answer specific to your question.
Whenever you pass name of a 2D Array, that name of array will be decayed into pointer to first element,
In a multi-dimensional array, as multi dimensional array is array of arrays, so first element will be array itself.
So name of 2D array will be decayed to pointer to array, ie pointer to first row having number of elements equal to number of columns in your 2D array.
Remember 2D array is received in a function as pointer to array not pointer to pointer.
int main()
{
int arr[2][3];
display(arr);
............
}
void display( int (*arr)[3])
{
}
Please look at this peice of code :-
#include<stdio.h>
int main()
{
int arr[2][2]={1,2,3,4};
printf("%d %u %u",**arr,*arr,arr);
return 0;
}
When i compiled and executed this program i got same value for arr and *arr which is the starting address of the 2 d array.
For example:- 1 3214506 3214506
My question is why does dereferencing arr ( *arr ) does not print the value stored at the address contained in arr ?
*arr is type integer array of length 2, so it shares the same address as arr. They both point to the beginning of their arrays, which is the same location.
in C, a 2d array is not represented in memory as an array of arrays; rather, it is a regular 1d array, in which the first given dimension is needed in order to calculate the right offset within the array at execution time. This is why in a multi-dimensional array you always need to specify all the dimensions except the last one (which is not required); for example, if you declare an array like
int a[2][3][4];
the array would be represented in memory as a single array of 2*3*4 elements in total. Trying to access the element at position (i,j,k), will actually be translated into accessing the element 3*i+4*j+k in the plain array. In some sense, the initial dimensions are needed to know where to put "row breaks" in the 1d array.