This might be a stupid question, but I have a little problem with understanding of C Pointers. Even more when it comes to arrays. For example:
char ptr[100];
ptr[0]=10;
fprintf(stderr, "&ptr: %p \n ptr: %p \n*ptr: %d\n", &ptr, ptr, *ptr);
if ( &ptr == ptr ) {
fprintf(stderr, "Why?\n");
}
How is this even possible? 'ptr' is at the adress &ptr. And the content of ptr is the same as &ptr. Then why is *ptr = 10 ???
The address of the first element of the array is the same as the address of the array itself.
Except when it is the operand of the sizeof or address-of & 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 implicitly converted ("decay") to type "pointer to T" and the value will be the address of the first element in the array.
If the expression a is of type "N-element array of T", then the expression &a is type "pointer to N-element array of T", or T (*)[N].
Given the declaration
T a[N];
then the following are all true:
Expression Type Decays to
---------- ---- ---------
a T [N] T *
&a T (*)[N] n/a
*a T n/a
The expressions a and &a both evaluate to the same value (the location of the first element in the array), but have different types (pointer to T and pointer to array of T, respectively).
ptr (which, as sbi says, is really an array) decays to &(ptr[0]) (char * to first element)
This is the same address as &ptr (a char (*) []), even though they are different types.
int arr[5];
arr[0]= 7;
fprintf(stdout,"%p %p %d",&arr[0],arr,*arr);
if( (int)&arr == (int)arr ) printf("good\n");
else printf("bad\n");
return 0;
}
This will work....
Related
#include<stdio.h>
void main()
{
char s[10][10];
int i;
for(i=0;i<4;i++)
scanf("%s",s[i]);
printf("%s",s);
printf("%s",s+1);
printf("%s",s[1]+1);
}
When I type the above line of code first printf statement will print the first string and second printf will print the second string since s[1] is equivalent to s+1. But the third printf will print the second string starting from the second character.
If s[1] is equivalent to s+1 why s[1]+1 does not give the result of s+2?
I do not get the idea of address calculation for 2D string array.
The way pointer arithmetic works, s[i] is equal to *(s + i). So s[1]+1 is actually *(s + 1) + 1, which is not the same as either s + 2 or *(s + 2).
So, let's talk about pointer arithmetic for a second. Given a pointer to any type T:
T *p;
the expression p+1 will evaluate to the address of the next object of type T. So if T is int, then p+1 will give us the address of the next int object after p. If p is 0x8000 and sizeof (int) is 4, then p+1 evaluates to 0x8004.
Where things get fun is if we're working with array expressions. Assume the following:
T a[N];
Except when it is the operand of the sizeof or unary & operators, an expression of type "N-element array of T" will be converted ("decay") to an expression of type "pointer to T" and its value will be the address of the first element of the array.
So if we write
int a[10];
int *p = a + 1;
the expression a is converted from "10-element array of int" to "pointer to int", and the value of a is the address of the first element (i.e., &a[0]). So the expression a + 1 gives us the address of the next integer object following a, which just happens to be &a[1]1.
Now assume we're working with a 2-D array:
int a[2][3];
int (*p)[3] = a + 1;
The expression a has type "2-element array of 3-element array of int". In this case, a "decays" to type "pointer to 3-element array of int", or int (*)[3]. So a + 1 gives us the address of the next *3-element array of int". Again, assuming a starts at 0x8000 and sizeof (int) is 4, then a + 1 evaluates to 0x800c
1. The expression a[i] is evaluated as *(a+i); that is, we're offsetting i elements from the address specified by a and dereferencing the result. Note that this treats a as a pointer, not an array. In the B language (from which C is derived), the array object a would have been a pointer object that contained the address of the first element (a[0]). Ritchie changed that in C so that the array expression would be converted to a pointer expression as necessary.
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;
Suppose we have
int a[2][3] ;
int (*p)[3]=a; // is ok
int (*p)[3]=&a[0]; // is also ok
but why is
int (*p)[3]=a[0];
producing errors , although a[0] gives first array's address(as 2d arrays are array of array) and seems more
okay than &a[0] which gives address of first element of first array still is ok but why?
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[2][3];
Then the following are true:
Expression Type Decays To Equivalent Value
---------- ---- --------- ----------------
a int [2][3] int (*)[3] &a[0]
&a int (*)[2][3] n/a n/a
*a int [3] int * a[0]
a[i] int [3] int * n/a
&a[i] int (*)[3] n/a n/a
*a[i] int n/a a[i][0]
a[i][j] int n/a n/a
Note that a, &a, *a, a[0], &a[0], and &a[0][0] all yield the same value (the address of the first element of the array is the same as the address of the array), but the types are different.
As you can see from the table above, the expression a[0] has type "3-element array of int"; since that expression is not the operand of the sizeof or unary & operators, it is converted to an expression of type "pointer to int", which is not compatible with "pointer to 3-element array of int", which is why int (*p)[3] = a[0]; throws an error.
Because a[0] is not a pointer type, but an int[3] type. A block of 3 integers which can be assigned to such, but not to a pointer.
int (*p)[3]=a; // is OK
because a is of type int (*)[3] (pointer to an array of 3 ints), after decay to the first element which is also the type of p. Assignment is legal.
int (*p)[3]=&a[0]; // is also OK
because &a[0] is also of type int (*)[3] (address of the first row)
int (*p)[3]=a[0]; // is not OK
because a[0] is of type int * after decay to the first element of row 0. Assignment of different pointer types is illegal.
How a[0] can be of type int or int[3] as we have declared it a 2d array
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*.
could you tell my why the value of a referenced
array and the value of the array itself has the same value?
i know a is a type of int* but with &a it should be int** or am i wrong??
so the value should be a pointer to the a int pointer.
example code:
#include <stdio.h>
int main()
{
int a[10];
printf("a without ref.: 0x%x\n",a);
printf("a with ref.: 0x%x\n",&a);
return 0;
}
http://ideone.com/KClQJ
Name of the array decays to an pointer to its first element in this case.
Name of the array will implicit convert to a pointer ,except for two situation ,the one situations is "&array",the other is "sizeof(array)".In both cases,name of the array is a array ,not a pointer .
For example:
int a[10];
int *p;
p = a; //a is a pointer
p = &a; //a is a array,&a is a constant pointer
sizeof(a); //a is array
Given an array declaration T a[N], the expression &a has type "pointer to N-element array of T (T (*)[N]) and its value is the base address of the array. In that respect, the unary & operator behaves the same for arrays as it does for any other data type.
What's hinky is how C treats the array expression a. 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 array expression of type "N-element array of T" (T [N]) will be replaced with ("decay to") a pointer expression of type "pointer to T" (T *) and its value will be the address of the first element of the array. IOW, a == &a[0].
Since the address of the first element of the array is the same as the base address of the entire array, the expressions a and &a yield the same value, but the types are different (T * as opposed to T (*)[N]).
if there is int *p which point a, then,
a+0 == &a[0] == p+0 == &p[0] : address
*(a+0) == *(&a[0]) == *(p+0) == *(&p[0]) : data
a == &a == &a[0]