This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
C: How come an array’s address is equal to its value?
C pointer : array variable
Considering a multidimensional Array:
int c[1][1];
Why all of the following expression points to the same address??
printf("%x", (int *) c); // 0x00000500
printf("%x", *c); // 0x00000500
printf("%x", c); // 0x00000500
How would a pointer's actual value and it's derefernced value can be the same?
Under most circumstances1, an expression of type "N-element array of T" will be converted ("decay") to expression of type "pointer to T", and the value of the expression will be the address of the first element in the array.
The expression c has type int [1][1]; by the rule above, the expression will decay to type int (*)[1], or "pointer to 1-element array of int", and its value will be the same as &c[0]. If we dereference this pointer (as in the expression *c), we get an expression of type "1-element array of int", which, by the rule above again, decays to an expression of type int *, and its value will be the same as &c[0][0].
The address of the first element of the array is the same as the address of the array itself, so &c == &c[0] == &c[0][0] == c == *c == c[0]. All of those expressions will resolve to the same address, even though they don't have the same types (int (*)[1][1], int (*)[1], int *, int (*)[1], int *, and int *, respectively).
1 - the exceptions to this rule are when the array expression is an operand of the sizeof, _Alignof, or unary & operators, or is a string literal being used to initialize another array in a declaration
You just have to think: where is the first position on this array?
Suppose it's on 0x00000050 in your memory space. What is the first item in your array? It's c[0][0], and its address is 0x00000050. Sure enough, the address of the first position is the same of the array. Even if you do c[0] only, it still points to the same address, as long as you cast it to the right type.
But you should not confuse pointers to arrays.
How would a pointer's actual value and it's derefernced value can be the same
It's not a pointer, it's an array.
See Q&A #3 & #4
c is the address of the array. c is also the address of the first element.
Related
I want to understand where exactly in code an array gets converted to a pointer. For example:
void foo( int* pData, int len){}
int main(void){
char data[] = "Hello world";
foo( (int*)data, sizeof(data));
return 0;
}
I know that an array decays to a pointer to the first element if it is assigned to a pointer. However in the example above, I typecast the array data to int* first before passing it in function and assigning it to a pointer. Does the conversion/decay to pointer occurs at the typecasting point ? If so, isn't it true to say that the typecasting operation has the same effect as using the assignment operator with respect to array conversion/decay? Also would sizeof(data) be equal to the address length or array length?
Thank you for help!
The conversion of arrays to pointers in C is spelled out in section 6.3.2.1p3 of the C standard:
Except when it is the operand of the sizeof operator, the
_Alignof operator, or the unary & operator, or is a string
literal used to initialize an array, an expression that has
type "array of type" is converted to an expression with type "pointer
to type" that points to the initial element of the array
object and is not an lvalue. If the array object has
register storage class, the behavior is undefined.
This means that the array is immediately converted to a pointer anywhere it is used except for the three cases listed above.
So applying the above to (int*)data, data is the operand of the typecast operator. Since this operator is not one of the ones listed above, data in this expression is converted from char [12] to char *, then the cast converts the char * to an int *.
Also, as mentioned above, the array is not converted when passed to sizeof. This means sizeof(data) evaluates to the size of char [12] which is 12.
Outwith the declaration, you can consider data to be equivalent to a pointer to the start of the array, but with the following exceptions:
sizeof(data) will give you the size of the array in bytes.
_Alignof(data) will be the same as _Alignof(*data) (and both give you the alignment of the type of the array elements)
&data has the same value as just data, but have a type of char (*)[sizeof(data] so arithmetic will use the full size of the array. Eg &data+1 will give you the address after the whole array rather than the address of the second element. See How come an array's address is equal to its value in C?
you can't change it's value (ie in this sense it is equivalent to a char *const).
When you call your function, you are taking the value of data (ie the address of the start of the array) and typecasting to an int *. The resulting int * behaves like any other int * and the exceptions don't apply, this is the 'decay'.
This question already has answers here:
How come an array's address is equal to its value in C?
(6 answers)
Closed 6 years ago.
So I almost went all hurr durr on my classmates when they wrote that
&array gives you address of the first element
But turns out they are right. This sounds like inconsistency to me. We're talking about array defined like this:
int numbers[] = {1,2,3,4};
The variable numbers is (I think) then of type int* const. I'd think that pointer to that would be int** const. But apparently this expression evaluates as true:
if(&numbers == numbers) {
printf("Pointer to array is still the same array!\n");
}
And of course, this then also is true:
int* first_elm_ptr = &numbers;
if(*first_elm_ptr == *numbers)
printf("%d == %d\n", *first_elm_ptr, *numbers);
So apparently you cannot get a pointer to the variable holding address of that array. Expression &numbers is essentially meaningless. Maybe it is even removed by compiler.
How's that possible? I am very confused right now! How does standard explain this behaviour? I made an ideone test code to verify this: http://ideone.com/pYffYx
The address of an array and the address of the first element of the array are essentially same value (same address location). They differ in type.
Expression &numbers is essentially meaningless
No, it is not.
In your case,
&numbers is of type int (*) [4]
numbers is of type int [4], and in some casesNote, it decays to int *.
Note:
Quoting C11, chapter §6.3.2.1
Except when it is the operand of the sizeof operator, the _Alignof operator, or the
unary & operator, or is a string literal used to initialize an array, an expression that has
type ‘‘array of type’’ is converted to an expression with type ‘‘pointer to type’’ that points
to the initial element of the array object [....]
This question already has answers here:
How come an array's address is equal to its value in C?
(6 answers)
Closed 7 years ago.
The following program prints that a and array share the same address.
How should I understand this behavior?
Is it &arr the address for the pointer arr, which contains the beginning address the 10 chars?
#include <stdio.h>
int main()
{
char arr[10] = {0};
char* a = (char*)(&arr);
*a = 1;
printf("a=%p,arr=%p.\n", a, arr);
printf("%d\n", arr[0]);
return 0;
}
When you allocate an array in C, what you get is something like the following:
+---+
arr[0]: | |
+---+
arr[1]: | |
+---+
...
+---+
arr[N-1]: | |
+---+
That's it. There's no separate memory location set aside for an object named arr to store the address of the first element of the array. Thus, the address of the first element of the array (&arr[0]) is the same value as the address of the array itself (&arr).
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.
So the type of the expression arr in the first printf call is char [10]; by the rule above, the expression "decays" to type char *, and the value is the address of arr[0].
In the expression &arr, arr is the operand of the unary & operator, so the conversion isn't applied; instead of getting an expression of type char **, you get an expression of type char (*)[10] (pointer to 10-element array of char). Again, since the address of the first element of the array is the same as the address of whole array, the expressions arr and &arr have the same value.
In idiomatic C, you should write char *a = arr; or char *a = &(arr[0]);. &arr is normally a char **. Even if modern (C++) compilers fixe it automatically, it is not correct C.
As arr is an array of char, arr[0] is a char and arr is the same as &(arr[0]) so it is a char *. It may be strange if you are used to other languages, but it is how C works. And it would be the same if arr was an array of any other type including struct.
The address printed out by arr and a is the memory address of the first element of the array arr. (Remember, the name of an array is always a pointer to the first element of that array.) This is because after you have defined the array arr, you define a as a pointer to the same address in memory.
According to the C Standard (6.3.2.1 Lvalues, arrays, and function designators)
3 Except when it is the operand of the sizeof operator or the unary &
operator, or is a string literal used to initialize an array, an
expression that has type ‘‘array of type’’ is converted to an
expression with type ‘‘pointer to type’’ that points to the initial
element of the array object and is not an lvalue. If the array object
has register storage class, the behavior is undefined.
The address of an array is the address of its first element. So though these types are different
char ( * )[10] ( that corresponds to &arr ) and char *(that is used in the casting in statement
char* a = (char*)(&arr); ) they will have the same value that is the address of the first element of the array.
If you would not use the casting then the correct definition of the pointer initialized by expression &arr would be
char ( *a )[10] = &arr;
The difference is seen then the pointer is incremented. For your definition of pointer a the value of expression ++a will be greater sizeof( char) than the initial value . For the pointer I showed the value of expression ++a will be greater 10 * sizeof( char ) than the initial value.
In your case the type of expression *a is char and you may write *a = 1; while in my case the type of expression *a will be char[10] and you may not write *a = 1;
I thought when you try to get the address of an array, it returns the address of the first element it holds.
int *j;
int a[5]={1,5,4,7,8};
Now j=&a[0]; works perfectly fine.
Even j=a also does the same function.
But when I do j=&a it throws an error saying cannot convertint (*)[5]' to int*' in assignment
Why does it happen? &a should be the first element of the array a, so it should give &a[0].
But instead it throws an error. Can somebody explain why?
The C standard says the following regarding how arrays are used in expressions (taken from C99 6.3.2.1/3 "Lvalues, array, and function designators):
Except when it is the operand of the sizeof operator or the unary &
operator, or is a string literal used to initialize an array, an
expression that has type ‘‘array of type’’ is converted to an
expression with type ‘‘pointer to type’’ that points to the initial
element of the array object
This is commonly known as "arrays decay to pointers".
So the sub-expression a in the following larger expressions evaluates to a pointer to int:
j=&a[0]
j=a
In the simpler expression, j=a, that pointer is simply assigned to j.
In the more complex expression, j=&a[0], the 'index' operator [] is applied to the pointer (which is an operation equivalent to *(a + 0)) and the 'address-of' operator is applied to that, resulting in another pointer to int that gets assigned to j.
In the expression j=&a, the address-of operator is applied directly to the array name, and we hit one of the exceptions in the above quoted clause: "Except when it is the operand of ... the unary & operator".
Now when we look at what the standard says about the unary & (address-of) operator (C99 6.5.3.2/3 "Address and indirection operators"):
The unary & operator returns the address of its operand. If the
operand has type "type", the result has type "pointer to type".
Since a has type "array of 5 int" (int [5]), the result of applying & to it directly has type "pointer to array of 5 int" (int (*)[5]), which is not assignable to int*.
The type of a and &a is not the same even though they contain the same value, i.e., base address of the array a.
j = a;
The array name a here gets converted to a pointer to its first element.
Try to see what values you get via these statements to understand where the difference lies:
printf("%p", a+1);
printf("%p", &a+1);
c is a strongly typed language. Assignment such as j=a; is allowed only if j and a are of the same type or the compiler can safely convert a to j. In your case, type of j is int * while the type of &a is int (*)[5]. The compiler does not know how to automatically convert an object of type int (*)[5] to an object of type int *. The compiler is telling you exactly that.
a is an array of 5 ints. The pointer to a is a pointer to an array of five integers, or int (*)[5]. This is not compatible with an int * because of pointer arithmetic: If you increment a variable of type int *, the address in the variable increases by 4 (assuming 4 byte integers), so that it points to the next integer. If you increment a variable that points to an array of 5 integers, the address in the variable increases by 20 (again assuming 4 byte integers), so that it points to the next array of five integers.
Perhaps what's confusing is that the value give by a and &a is the same, as you said. The value is the same but the type is different, and the difference is most obvious when you do arithmetic on the pointers.
I hope that helps.
int a[10];
printf("%p ", &a);
will display the address of array a.
So, if I perform a redirection, *(&a), why is that I don't get value stored at a[0]. What is the rule in C language that states I should be getting address of a. Yes, it does make sense, I get address of a, since * and & will cancel each other leading to simply a, which is the address of a.
int a[10];
printf("%p ", (void *) &a); // address of the array
printf("%p ", (void *) a); // adress of the first element of the array
printf("%p ", (void *) *(&a));// same as above
Here, the value of a is the same as &a[0]. And the value *&a is the same as the value of a when the a object is an array of int.
Note that the printed address will be the same as they both start at the same address.
I added the void * cast which is required as p requires a void * argument.
The C rule that governs this is C 2011 6.3.2.1 3: “Except when it is the operand of the sizeof operator, the _Alignof operator, or the unary & operator, or is a string literal used to initialize an array, an expression that has type ‘‘array of type’’ is converted to an expression with type ‘‘pointer to type’’ that points to the initial element of the array object and is not an lvalue.”
a is an array of int. When you pass a to printf, the rule converts it to a pointer to int, and the value of that pointer is printed.
When you pass &a to printf: First, a is the operand of &, so the rule does not apply; a is not converted to a pointer to int; it remains an array of int. Second, the & is evaluated. &a yields the address of the array, and this address is printed. Since the address of the array is the same as the address of its first element, the address is printed.
Note that the type of the expression &a is “pointer to array of int”. So, when you have *&a, you are applying * to a pointer to an array of int, and the result is an array of int. Since the expression is an array of int, the rule applies, and this array of int is converted to a pointer to the first element, and the value of that pointer is printed.
The fact:
a[0] == *(a)
a[9] == *(a+9)
The type of the pointer that &a evaluates to is a pointer to an array (specifically a pointer to an int[10]). That's a different type that a pointer to the first element of the array, even if it's the same address.
printf("%d ", *&a[0]); will print the value of the first element of the array because &a[0] has type int*.