Single dimensional array address - c

char arr[10]="hello";
I guess &arr in this array is of type char(*)[10].
If I am right, what is the type of *(&arr)? Is it of type base address or address to first element in array?

Given:
char arr[10];
as you say, &arr is of type char (*)[10]. Of itself, *(&arr) is of type char [10], but in most contexts (other than sizeof()) it will become char * when it is used.
Sample code:
#include <stdio.h>
int main(void)
{
char arr[10] = "hello";
printf("arr[10] = \"%s\"\n", arr);
printf("arr = %p\n", arr);
printf("&arr = %p\n", &arr);
printf("*(&arr) = %p\n", *(&arr));
printf("sizeof(*(&arr)) = %zu\n", sizeof(*(&arr)));
printf("arr+1 = %p\n", arr+1);
printf("&arr+1 = %p\n", &arr+1);
printf("*(&arr) = \"%s\"\n", *(&arr));
return 0;
}
Sample output (GCC 4.7.1, Mac OS X 10.8.3):
arr[10] = "hello"
arr = 0x7fff4ff15500
&arr = 0x7fff4ff15500
*(&arr) = 0x7fff4ff15500
sizeof(*(&arr)) = 10
arr+1 = 0x7fff4ff15501
&arr+1 = 0x7fff4ff1550a
*(&arr) = "hello"
Note that although the values of arr and &arr are the same, the types are different. This is most clearly demonstrated by the arr+1 and &arr+1 lines. As you can see, incrementing &arr by one adds the sizeof of the object it points at (a char [10]) to the address.
You can extend the example to add other values as you see fit.

The expression *(&arr) is the same type as arr. The dereference and address-of operators cancel out each other out.
You use the address-of operator & to get the address, i.e. get a pointer. You use the dereference operator * to get the value of what a pointer points to. So using both of them like that doesn't make any sense in that context.

*(&arr) is of type base address, where as *(&arr[0]) is the first element in the array.

char arr[10];
arr has type "array of 10 chars" and &arr is "pointer to array of 10 chars." , *(&arr) is the same as arr, and has the same type, i.e, base address.
&arr[0] will yield a pointer that points to the first element address.

a, *(&a), &a[0] are same (base address of array a/ address of the first element of array a).

Related

When I point a pointer to an array. Why does the pointer and the index[0] of the array I am pointing to have different memory addresses?

#include <stdio.h>
int main()
{
int arr[5];
arr[0] = 10;
arr[1] = 20;
arr[2] = 30;
arr[3] = 40;
arr[4] = 50;
int *p = &arr;
printf("Memory address of first index: %p\n", &arr[0]);
printf("Memory address of pointer: %p\n", &p);
return 0;
}
OUTPUT
Memory address of first index: 000000000061FE00
Memory address of pointer: 000000000061FDF8
They are are not the same. Is my machine bad?
First of all the compiler should issue a message relative to this declaration
int *p = &arr;
The problem is that the right hand side expression has the type int( * )[5] while the initialized object has the type int * and there is no implicit conversion between these two pointer types.
You should write either
int *p = arr;
In this case the array designator is implicitly converted to a pointer to its first element. Or
int ( *p )[5] = &arr;
The pointer p occupies its own extent of memory. So its address is different from the address of the extent of the memory occupied by the array arr.
On the other hand, if you will output the value stored in the pointer p like for example
printf("Memory address stored in the pointer p: %p\n", ( void * )p);
then it will be equal to the address of the first element of the array arr
printf("Memory address of first index: %p\n", ( void )&arr[0]);
arr is an array. It and its elements start at some place in memory.
p is a pointer to the array. Its value is an address. That address needs to be stored somewhere else in memory. That place is different from where the array is stored.
printf("%p\n", (void *) p); prints the value of p, which will be the address of arr (and of &arr[0], since the first element is at the start of the array).
printf("%p\n", (void *) &p) prints the address of p, which is where p is.

A pointer to an address of an array

Why does this code output: 1 ≡ arr[0] and not &arr[0]?
My assumption is that after the assignment, ptr holds the address of &arr, which is a pointer to the first element of arr or arr[0].
So dereferencing the ptr should yield the value stored at that address, which is the memory location of the first element.
#include<stdio.h>
int main(void) {
int arr[] = { 1 };
int* ptr = &arr;
printf("%d\n", *ptr);
return 0;
}
A couple of things...
First, a doesn't store the location of a[0]. There is no object a that is separate from the array element a[0]. Basically what you have in memory is
Address
------- +------+
0x1000 a: | 0x01 | a[0]
+------+
In other words, the address of an array is the same as the address of its first element.
Unless it is the operand of the sizeof or unary & operators, the expression a will be converted ("decay") from type "1-element array of int" (int [1]) to "pointer to int" (int *) and the value of the expression will be the address of the first element in the array.
This means that the expressions &a, a, and &a[0] all yield the same address value; it's just the types of the expressions are different:
Expression Type Decays to
---------- ---- ---------
&a int (*)[1]
a int [1] int *
&a[0] int *
Which brings us to this line:
int* ptr = &arr; // int * = int (*)[1] - assignment of incompatible types
The compiler should have yelled at you about that line. You may want to dial up the warning level.
I added some print statements to your code:
#include<stdio.h>
int main(void) {
int arr[] = { 1 };
int *ptr = (int *)arr;
printf("%p\n", (void *)arr);
printf("%p\n", (void *)&arr);
printf("%p\n", (void *)&arr[0]);
printf("%p\n", (void *)ptr);
printf("%p\n", (void *)&ptr);
printf("%d\n", *ptr);
return 0;
}
It prints:
0x7ffe3fe37aa4
0x7ffe3fe37aa4
0x7ffe3fe37aa4
0x7ffe3fe37aa4
0x7ffe3fe37a98
1
Which means arr and ptr are on the stack: ptr is at 0x7ffe3fe37a98 and has the value 0x7ffe3fe37aa4, which is where the arr is stored.
Note that arr and &arr have the same value. See this question: How come an array's address is equal to its value in C?
My assumption is that after the assignment, ptr holds the address of &arr, which is a pointer to the first element of arr or arr[0].
That is correct.
So dereferencing the ptr should yield the value stored at that address
Also correct.
which is the memory location of the first element.
No. Since ptr is pointing to the first element, dereferencing yields the first element, which is 1.

Dereferencing a pointer to 2d array

I don't understand why when dereferencing a pointer to an array, the result is the address of the first value of the array
int array[2][2] = {{0,1},{0,1}};
int (*p)[2];
p = array;
p = address of a[0][0], p+1 = address of a[1][0],
*p = address of a[0][0], (*p)+1 = the address of a[0][1];
I understand that p is a pointer to an array of 2 integers, not a pointer to an integer. But if we print out the value of p, it's still the address of an integer. I want to know what's going on under the hood? Is p a pointer to an array of pointers? So we have to dereference it twice to get the value of the integer its pointing?
A pointer to an int,
int* p;
is a variable, stored in a location, that contains the address of another variable (int).
When we dereference it, we get the value of that variable. How does this process work exactly with a pointer to an array?
The address of an array is the same as the address of its first element.
Given the definition int array[2][2] = {{0,1},{0,1}};, the compiler arranges some location in memory to contain the int values 0, 1, 0, and 1. Let’s say that location has address 1000, and the int value 0 is stored in bytes 1000-1003, 1 is stored in 1004 to 1007, 0 is stored in 1008 to 1011, and 1 is stored in 1012 to 1015.
Where does the element array[0][0] start in memory? At location 1000.
Where does the array array start in memory? At location 1000.
Where does the array array[0] start in memory? At location 1000.
The array starts in memory at the same location its first element starts in memory. Also, array[0], which is itself an array, starts at the location 1000.
So, after p = array;, p points the location 1000. And the element array[0][0] also starts at location 1000. So, when you print p, as with printf("%p\n", (void *) p);, it is unsurprising you get the same result as when you print the address of array[0][0], as with printf("%p\n", (void *) &array[0][0]);.
An array is automatically converted to the address of its first element.
Next, let’s consider *p. The type of p is int (*)[2], a pointer to an array of 2 int. Therefore, *p is an array of 2 int.
In particular, *p is an array. Suppose we attempt to print it by passing it as an argument to printf. What happens?
In C, when an array is used in an expression, it is automatically converted to the address of its first element (except when the array is the operand of sizeof or unary & or is a string literal used to initialize an array). So, if you use *p as an argument to printf, it initially means array[0], but that array is converted to the address of its first argument. So passing *p as an argument actually passes &array[0][0] (or, equivalently &(*p)[0]).
Thus, printf("%p\n", (void *) *p); will print the same address as printf("%p\n", (void *) &a[0][0]);.
Value at an array can be accessed using
array[i] = *(array+i) (expansion of [i]).
Similarily, (*p)[i] = *(*(p+i)). So, we need to dereference twice to access the value.
If you want to access, array[0][0], you have to use *(*(p+0)+0) = **p;,
Similarily, array[0][1] can be accessed using *(*(p+0)+1) = *((*p)+1);
Note, *p points to first row (stores address of array[0][0]), and *(p+1) points to second row (stores address of array[1][0]).
Please check the below code :
#include <stdio.h>
int main()
{
int array[2][2] = {{1, 2}, {3, 4}};
int(*p)[2];
p = array;
printf("The address of array[0][0] is %p \n",&array[0][0]);
printf("The address of *p is %p \n",*p);
printf("The address of array[1][0] is %p \n",&array[1][0]);
printf("The address of *(p+1) is %p \n",*(p+1));
printf("The value of array[0][0] is %d \n",array[0][0]);
printf("The value of **p is %d \n",**p);
printf("The value of array[0][1] is %d \n",array[0][1]);
printf("The value of *((*p)+1) is %d \n",*((*p)+1));
return 0;
}
The output is:
The address of array[0][0] is 0x7fff6e8781a0
The address of *p is 0x7fff6e8781a0
The address of array[1][0] is 0x7fff6e8781a8
The address of *(p+1) is 0x7fff6e8781a8
The value of array[0][0] is 1
The value of **p is 1
The value of array[0][1] is 2
The value of *((*p)+1) is 2

Casting pointer syntax (to an array address like a smaller sized array) in C language

I have an array with 10 int elements, and I want to point a pointer to this array, not with full size but half. By this, I can reach the first 5 elements by using ptr and the second 5 elements by increasing pointer one ptr++.
I just want to know how can I CAST, I don't need to know workarounds or union or struct or anything else...
I just wonder the syntax of such a thing.
Here is the example that I struggle with ;
// Pointer to an integer
int *p;
// Pointer to an array of 5 integers
int (*ptr)[5]; // this could be void*
int arr[10];
// Points to 0th element of the arr.
p = arr;
// Points to the whole array arr.
ptr = (int[5]*)&arr; // when arr sized as 5 , ptr = &arr; gives result a pointer "ptr" with size of 5
printf("p = %p, ptr = %p\n", p, ptr);
p++;
ptr++;
printf("p = %p, ptr = %p\n", p, ptr);
return 0;
Note:
The answer is: ptr = (int(*)[5])&arr; (compiler's warning message helped me out to find this answer, it was not able to convert one to another type ... )
But I really don't know what is the () and why it is not the same thing as int*[5]. I really don't understand the purpose of parenthesis there.
If I understand what you’re asking for, this is what you want:
ptr = (int (*)[5]) &arr;
The expression &arr has type int (*)[10] (pointer to 10-element array of int). Since ptr has type int (*)[5] (pointer to 5-element array of int), we just need to cast the result of &arr to that type.
Remember the following precedence rules:
T *a[N]; // a is an array of pointer to T
T (*a)[N]; // a is a pointer to an array of T
T *f(); // f is a function returning pointer to T
T (*f)(); // f is a pointer to a function returning T
Unary * has a lower precedence than [] and (), so an expression like *a[i] is parsed as *(a[i]) - you’re dereferencing the result of a[i]. If a is a pointer to an array, then you need explicitly group * with a so you index into what a points to - (*a)[i].
Define a typedef to make the casting easier.
typedef int (*int5ptr)[5];
// Pointer to an integer
int *p;
// Pointer to an array of 5 integers
int5ptr ptr;
int arr[10];
// Points to 0th element of the arr.
p = arr;
// Points to the whole array arr.
ptr = (int5ptr)&arr;
printf("p = %p, ptr = %p\n", p, ptr);
p++;
ptr++;
printf("p = %p, ptr = %p\n", p, ptr);

C assigning the address of a 2D array to a pointer

I was reading through some lecture notes that in order for a pointer to reference a 2D array, it has to be given the address of the first element.
int a[10][10];
int *p = &a[0][0];
I've never tried this, so I was curious why isn't it enough to assign the array itself to the pointer, just as we do in a 1D case.
int a[10][10];
int *p = a;
The array is kept in an uninterrupted 'line' of memory anyway, and 2D arrays only have a different type, but the same structure as 1D arrays.
By doing this
int *p = &a[0][0];
I don't see how we give the pointer any more information than by doing this
int *p = a;
Or maybe all arrays regardless of their number of dimensions have the same type, the only difference being that multidimensional arrays store their extra dimensions before their first element and we need to jump over those memory spaces which remember sizes of an array's dimensions?
First, some background:
Except when it is the operand of the sizeof or unary & operators, or is a string literal being used to initialize another array in a declaration, an expression of type "N-element array of T" will be converted ("decay") to an expression of type "pointer to T", and the value of the expression will be the address of the first element of the array.
Given the declaration
int a[10][10];
the expression a has type "10-element array of 10-element array of int". Unless this expression is the operand of the sizeof or unary & operators, it will be converted to an expression of type "pointer to 10-element array of int", or int (*)[10].
Given that declaration, all of the following are true:
Expression Type Decays to
---------- ---- ---------
a int [10][10] int (*)[10]
&a int (*)[10][10]
*a int [10] int *
a[i] int [10] int *
&a[i] int (*)[10]
*a[i] int
a[i][j] int
&a[i][j] int *
Also,
sizeof a == sizeof (int) * 10 * 10
sizeof &a == sizeof (int (*)[10][10])
sizeof *a == sizeof (int) * 10
sizeof a[i] == sizeof (int) * 10
sizeof &a[i] == sizeof (int (*)[10] )
sizeof *a[i] == sizeif (int)
sizeof a[i][j] == sizeof (int)
sizeof &a[i][j] == sizeof (int *)
Note that the different pointer types int (*)[10][10], int (*)[10], and int * don't have to be the same size or have the same representation, although on the platforms I'm familiar with they do.
The address of the first element of the array is the same as the address of the array itself; thus, all of a, &a, a[0], &a[0], and &a[0][0] will yield the same value, but the types will be different (as shown in the table above).
So, assume we add the following declarations:
int *p0 = &a[0][0]; // equivalent to int *p0 = a[0];
int (*p1)[10] = &a[0]; // equivalent to int (*p1)[10] = a;
int (*p2)[10][10] = &a;
All of p0, p1, and p2 initially have the same value, which is the address of the first element in a; however, because of the different pointer types, the results operations involving pointer arithmetic will be different. The expression p0 + 1 will yield the address of the next int object (&a[0][1]). The expression p1 + 1 will yield the address of the next 10-element array of int (&a[1][0]). And finally, the expression p2 + 1 will yield the address of the next 10-element array of 10-element array of int (effectively, &a[11][0]).
Note the types of p1 and p2; neither is a simple int *, because the expressions being used to initialize them are not that type (refer to the first table).
Note the pattern; for an array type, the simpler the expression, the more complicated the corresponding type will be. The expression a does not refer to a single int object; it refers to a 10x10 array of int objects, so when it appears in an expression, it is treated as a pointer to an array of integers, not a pointer to a single integer.
The compiler knows that "a" is a pointer to ten integers. If you don't declare the dimensions, then the compiler sees the new pointer as a pointer to an unknown number of integers. This will work in your case, but it will generate a compiler warning because the compiler sees them as incompatible pointers. The syntax for what you are trying to do (without generating a compiler warning) is:
int a[10][10];
int *p1 = &a[0][0];
int (*p2)[10] = a;
printf("p1: %p p2: %p\n", p1, p2);
One reason this is important is pointer arithmetic:
p1++; //move forward sizeof(int) bytes
p2++; //move forward sizeof(int) * 10 bytes
You understanding is close, the difference is the type information. Pointer does has its type. For example int* p, the pointer type is int*, as int a[10][10], the corresponding pointer type is int *[10][10].
In your example, p and a do point to the same address, but they're different type, which matters when perform arithmetic operation on them.
Here's an example from this URL
Suppose now that we define three pointers :
char *mychar;
short *myshort;
long *mylong;
and that we know that they point to the memory locations 1000, 2000, and 3000, respectively.
Therefore, if we write:
++mychar;
++myshort;
++mylong;
mychar, as one would expect, would contain the value 1001. But not so obviously, myshort would contain the value 2002, and mylong would contain 3004, even though they have each been incremented only once. The reason is that, when adding one to a pointer, the pointer is made to point to the following element of the same type, and, therefore, the size in bytes of the type it points to is added to the pointer.
You are right, you can assign the array itself to the pointer:
int a[10][10] = {[0][0]=6,[0][1]=1,[1][0]=10,[1][1]=11};
int b[10][10][10] = {[0][0][0]=8,[0][0][1]=1,[0][1][0]=10,[1][0][0]=100};
int *p, *q, *r, *s;
p = &a[0][0];
q = a; // what you are saying
r = &b[0][0][0];
s = b; // what you are saying
printf("p= %p,*p= %d\n",p,*p);
printf("q= %p,*q= %d\n",q,*q);
printf("r= %p,*r= %d\n",r,*r);
printf("s= %p,*s= %d\n",s,*s);
And the output is:
p= 0xbfdd2eb0,*p= 6
q= 0xbfdd2eb0,*q= 6
r= 0xbfdd3040,*r= 8
s= 0xbfdd3040,*s= 8
They point to the same address, regardless of the dimension of the matrix. So, what you are saying is right.
Well in 2D array, the outcome of *a and a is the same, they all point to the first address of this 2D array!
But if you want to define a pointer to point to this array, you could use int (*ptr)[10] for example.
You are right, 1D and 2D share the same structure, but 2D has some additional manipulation on pointers like above.
So all in all, in 2D array, a, *a and &a[0][0] prints the same address, but their usages may vary.
Like this:
#include<stdio.h>
int main() {
int a[10][10];
int *pa1 = &a[0][0];
int *pa2 = *a;
printf("pa1 is %p\n", pa1);
printf("pa2 is %p\n", pa2);
printf("Address of a is %p\n", a);
// pointer to array
int (*pa3)[10];
pa3 = a;
printf("pa3 is %p\n", pa3);
return 0;
}
They print the same address.

Resources