Does name of a 2D array give its base address in C? - c

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])
{
}

Related

How to get an adress of a static array in C

Got this
char array1[10][10];
Is it possible to get address of array1 ? In which type could I stock it ?
Already tried the following:
char *hold[10][10];
hold = &array1;
But doesnt work, ideas?
What you have now is a 2D array of char *. You need some parenthesis in this type.
char (*hold)[10][10];
This is a pointer to a 2D array of type char[10][10] that you can assign &array to.
Typically you want to get the address of the first element, not a pointer to a 2D array. The first element is a char [10] (a 1D array), so you need
char (*hold)[10] = array1;
Notice array1 is converted to a pointer to the first element for the assignment. This is not recursively applied!
That way you can dereference the pointer exactly like for the original array:
hold[4][5]
For the char (*hold)[10][10] approach, the syntax is more complicated and not really ideomatic. Accessing an element of the array would require dereferencing the pointer first:
(*hold)[4][5]

Why Do I need that extra asterix using 2D array?

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

is a==*a?? A query regarding pointers

int main()
{
int a[4][3] = {10,20,30,40,50,60,70,80,90,100,110,120};
printf("%d",((a==*a) && (*a==a[0])));
return 0;
}
Prints 1 on the console.
Anyone has logical explanation??
Arrays are converted to pointer when used in an expression except when they are an operand of sizeof and unary & operator. a and *a are of different types (after decay) but have the same address value.
a decays to pointer to first element (first row) of array and is of type int (*)[3].
*a dereference the row pointed by a and further decayed to pointer to first element of first row. It is of type int *.
a[0] is representing the first row which is of type int [3]. In expression it decays to pointer to first element of first row and is of type int * after decay.
As the address of an array the address of first byte, therefore address of an array, address of first row and address of first element all have the same value. So, after decay, all of a, *a and a[0] points to same location.
Here is a graphical view of the above explanation:
What exactly is the array name in c?
Is a==*a?
The answer is yes if the array a is multi dimensional array.
so what if it is single dimensional? let me give you an example.
void main()
{
int a[4]={1,2,3,4};
printf("%d",((a==*a)&&(*a==a[0])));
}
The answer in this case would be 0.
This is because 'a' represent address of array or address of first element of array but *a represent value(pointer to that value). the address and value are different types so answer would be 0.
But in case of multi dimensional arrays 'a' represented as a[0][0] because it represent pointer to the first element of first sub array of multi dimensional array.
So the answer is yes if the array is multi dimensional array

2D array and pointers

int stud[5][2] = {{1,2},{3,4},{5,6},{7,8},{9,8}};
printf("%u %u",*(stud+1),stud+1);
printf("%u, %u", &stud,stud);
Why this statement prints similar values, stud[1] or *(stud+1) is actually an array hence must get the base address i.e &stud[0][0], but stud itself is a pointer to an array of array. Also the third statement prints identical values.
Your observations are correct concerning the expressions are all address-results. But the types of those addresses per the standard are different. Your phrase "but stud itself is a pointer to an array of array". is not accurate. stud is an array of arrays. Pointers are not arrays. After decades of trying to come up with a solid vernacular that describes how it works, and refusing steadfastly to walk the "decay" plank (a word that appears exactly one times in the C standard and even there it is used as a verb-footnote), the best I could come up with is this:
Pointers are not arrays. A pointer holds an address. An array is an address.
Each expression is shown below Given int stud[5][2];
stud int (*)[2]
stud+1 int (*)[2]
*(stud+1) int *
&stud int (*)[5][2]
Remembering that, per the standard, the expressive value of an array is the address of its first element, and pointer-to-element-type is the type of said-address. In both outputs each pair of expressions have equivalent addresses, but they're different types. This is verifiable with some expansion of the original code:
#include <stdio.h>
int main()
{
int stud[5][2] = {{1,2},{3,4},{5,6},{7,8},{9,8}};
printf("%p %p\n", *(stud+1), stud+1);
printf("%p %p\n", &stud,stud);
int (*p1)[2] = stud+1; // OK
// int (*p2)[2] = *(stud+1); // incompatible types
int *p3 = *(stud+1); // OK
int (*p4)[5][2] = &stud; // OK
return 0;
}
int stud[5][2] = {{1,2},{3,4},{5,6},{7,8},{9,8}};
The above statement defined stud to be an array of 5 elements where each element is of type int[2], i.e., an array of 2 integers. It also initializes the array with an initializer list.
Now, in the expression stud + 1, the array stud decays into a pointer to its first element. Therefore, stud + 1 evaluates to &stud[1] and is of type int (*)[2], i.e., a pointer to an array of 2 integers . *(stud + 1) is then *(&stud[1]), i.e., stud[1]. stud[1] is again an array type, i.e., int[2], so it again decays to a pointer to its first element, i.e., &stud[1][0] (which is the base address of second element of the array stud[1]) in the printf call.
Please note that stud + 1 and *(stud + 1) evaluate to the same address but they are not the same type.
Similarly, &stud and stud decay to the same address but they are different types. stud is of type int[5][2] where as &stud is of type int (*)[5][2].
Why this statement prints similar values, stud[1] or *(stud+1) is actually an array hence must get the base address i.e &stud[0][0], but
stud itself is a pointer to an array of array.
You are wrong here. The base address of stud[1] or *(stud + 1) is &stud[1][0] and not &stud[0][0]. Also, stud is not a pointer but an array type. It decays to a pointer to its first element in some cases like here but it does mean it is a pointer.
Also, you should use %p conversion specifier for printing addresses.
Without using any decaying syntax it may be clearer (these are the same addresses as your code; the first line is in the opposite order; and my parentheses are redundant but hopefully it improves clarity of this example):
printf( "%p %p\n", &(stud[1]), &(stud[1][0]) );
printf( "%p %p\n", &(stud), &(stud[0]) );
In both cases the first address on the line matches the second because the first element of an array lives at the same address as the array. Arrays can't have initial padding, and in C the address of an object is the address of its first byte.
The first element of stud is stud[0], and the first element of stud[1] is stud[1][0].
Since all of those values you are trying to display are all pointers you should use %p instead of %u. If you do that you will see that the addresses pointed to:
printf("%p, %p", &stud,stud);
are different than:
printf("%p %p",*(stud+1),stud+1);
because as you said stud is a pointer to an array of array.
Lets analyze the program
int stud[5][2] = {{1,2},{3,4},{5,6},{7,8},{9,8}};
Now address will be like this (assuming 2 byte integer). Brackets denote corresponding elements in array.
1 element of 2-D array ---> 4001(1) 4003(2)
2 element of 2-D array ---> 4005(3) 4007(4)
3 element of 2-D array ---> 4009(5) 4011(6)
4 element of 2-D array ---> 4013(7) 4015(8)
5 element of 2-D array ---> 4017(9) 4019(8)
We know that arr[i] gives the ith element of array. So when we say stud[0] we expect 0th element of array stud[5][2].
We can assume 2-d array as collection of 1-d array. So with statement like printf("%u",stud[0]) we exptect 0th element to get printed and what is 0th element for this array. It is one dimensional array. We know that just mentioning 1-D array gives its base address. Hence printf would print base address of 0th 1-D array and so on.
With this information we can analyze your problem.
Remember stud is 2-D array. stud is treated as pointer to zeroth element of 2-D array. So (stud + 1) would give address of 2nd element of 2-D array. And thus printing (stud+1) would print address of 2nd element of stud array. What is it. It will be 4005 from above addresses.
Now lets see why *(stud +1) also gives the same value.
Now we know that *(stud +1) is equivalent to stud[1]. From above we know stud[1] would print base address of 2nd 1-D array. What is 1-d array at 2nd position it is (3,4) with address (4005,4007). So what is it base address. It is 4005. Thus *(stud+1) also prints 4005.
Now you say stud[0] and &stud[0] print the same value.
From above stud[0] is 1-d array and printing it gives its base address. Now so &stud[0] should give address of 1-D array which is same as its base address. Thus they print the same address.
Similar explanation will hold for other cases.

Difference between x and &x in c

What is the difference between a pointer to an array and a pointer to the first element of an array? In most cases they would be same. Please specify an example when they are not the same. Thank you.
The type is different:
int x[1] = {0};
&x[0] is a pointer to the first element of x array and is of type int *.
&x is a pointer to x array and is of type int (*)[1].
But their value is the same because there is no padding in arrays:
(int *) &x == x /* in a value context the expression evaluates to 1 */
The identity of an object is given by the pair (address, type). Different objects can have the same address as long as their types are different, in which case one is a subobject of the other.
This is the case with arrays: The array is an object, and the array elements are objects, and the array elements are subobjects of the array. The first element happens to have the same address as the array itself. Something similar is true for structs and the first struct member.
So if you have an array T a[N], then the type of a is T[N] and the type of a[0] is T, and so the address of the array is
T (*array_addr)[N] = &a;
and the address of the first element is
T * elem_addr = &a[0];
Since a naked array expression decays to a pointer to the first element under certain conditions, the last line could also be written as T * elem_addr = a;, which has the exact same meaning.
The main difference is that when you obtain the reference to an array, it decays to a pointer and sizeof can't be used anymore on it to obtain the array size, eg:
int array[10];
printf("%d\n", sizeof(array)/sizeof(array[0]));
printf("%d\n", sizeof(&array)/sizeof(array[0]));
This prints on x64:
10
2
Of course you will lose any reference to the size of the array even if you convert to a pointer without any use of the & operator:
printf("%d\n", sizeof((int*)array)/sizeof(array[0])); // prints 2
you can print the a and &a, than print a++ and &a++. Through the result, you will know the answer, just try it. a means a element address, and &a means the array address. int a[] = {1, 2 };
Pointer to an array and pointer to the first element of an array is represented as q=&a and p=a. When you increment the p as p++ it will point to the next element in array but when you increment q++ it will give to the next location to the last element in that array. Thus pointer to an array represents to whole array while pointer to first element in array represents only to the first element in array.

Resources