I ran into a pointer dereferencing problem.
In C, &a means the address of a. If a is a pointer ,then &a simply means the address of that pointer.
So if we have:
char ptr [] = "abcd"
ptr should be a pointer pointing to the first character, which is 'a'. therefore,
&ptr
should be the address of ptr, which is different than the address of 'a'. However, when I tried the following code I got really confused:
int main()
{
char a [] = "abcd";
printf("0x%X 0x%X", a, &a);
}
Output: 0xBF7E62AB 0xBF7E62AB
Can someone explain why a and &a have the same value? Based on my understanding they should be different. thanks in advance
So if we have: char ptr [] = "abcd", ptr should be a pointer pointing to the first character.
No. Not at all.
ptr is an array. And an array is not a pointer.
Indeed, if you declared ptr as a real pointer, then you would get the expected behavior:
const char *ptr = "abcd";
printf("ptr = %p, &ptr = %p\n", (void *)ptr, (void *)&ptr);
As to why the address of the array is the same as the address of its first element: it's quite logical. The array represents a contiguous sequence of elements. The address of the array is where the array begins in memory. It begins where its first element begins. So, the address of the first element is (rather "can be" -- the standard does not mandate this behavior) the same as the address of the array itself.
+-----------+-----------+- - - -
| element 1 | element 2 |
+-----------+-----------+- - - -
^ start of array
^ start of first element
Can someone explain why a and &a have the same value? Based on my understanding they should be different.
In the statement
printf("0x%X 0x%X", a, &a);
Both a and &a are of different types. a is of char * type (after decay) while &a is of char (*)[5] type.
a decays to a pointer to the first element, therefore a is the address of first element of the string. While &a is the address of the string "abcd" and it is equal to the address of first element.
An array is not a pointer. That's right when you said &p is the address of the pointer, if p is definied like this:
char *p;
An array is different and don't has exactly the same behavior.
With the arrays:
char a[] = "abc";, &a[0] is the address of the first element in your array, which is the same as a.
char a[] = "abcd" does not declare a pointer a to "abcd" but an array. Even if an array can decay to a pointer, it is a different type for which &a and a yield the same address.
Basically a yields the address to the first element of the array, so it is equivalent to &a (and to &a[0]).
Arrays will always reference the location where it is stored in memory, that's why when you print a, it gives you the address where it is, which is equal to getting the pointer pointing at the array (&a)
To get the behaveour you seek change
char a [] = "abcd";
to
char *a = strdup("abcd");
or for a readonly string
const char *a = "abcd";
You will then get a different address for a and &a.
When passing an array to a function, the array gets converted to a pointer.
With your original program try
printf("%d %d\n",sizeof(a),sizof(&a));
The first will vary with the size of the string, the second will be based on the pointer size on your machine.
Related
Can anyone explain how these values will be printed and why p and *p are returning the same values.
#include <stdio.h>
int main(){
int arr[] = {1,2,3,4};
int (*p)[4];
p = &arr;
printf("%u %u %u %u %u", arr, &p, p, *p, **p);
p++;
printf("\n%u %u %u %u %u", arr, &p, p, *p, **p);
return 0;
}
outputs on my machine are as follows:
2686768 2686764 2686768 2686768 1
2686768 2686764 2686784 2686784 2686792
Your example is messy, but pointer arithmetic is messy in general, disrespectful to types. Your example does not make sense from a type theory point of view.
arr points to the first element of the array. Note that arr[i] is equivalent to *(arr+i). arr is a 4-elements array of type int.
p is a pointer to a 4-element array of type int.
You assign to p the address of &arr, which has the same address as arr (but the type is different, see below).
Then you print it out and this means:
arr is the address of the first element of the array
&p is the address of p
p is the address of &arr (whole array), which is the address of arr, which is the address of the first element in the array
*p is the address of arr, which is the address of the first element in the array
**p is trying to dereference *p, which is dereferencing arr, which actually is the first element of the array
After you increment p++: arr and &p don't change, the rest does
From the C Book
We have already emphasized that in most cases, the name of an array is
converted into the address of its first element; one notable exception
being when it is the operand of sizeof, which is essential if the
stuff to do with malloc is to work. Another case is when an array name
is the operand of the & address-of operator. Here, it is converted
into the address of the whole array. What's the difference? Even if
you think that addresses would be in some way ‘the same’, the critical
difference is that they have different types. For an array of n
elements of type T, then the address of the first element has type
‘pointer to T’; the address of the whole array has type ‘pointer to
array of n elements of type T’; clearly very different. Here's an
example of it:
int ar[10];
int *ip;
int (*ar10i)[10]; /* pointer to array of 10 ints */
ip = ar; /* address of first element */
ip = &ar[0]; /* address of first element */
ar10i = &ar; /* address of whole array */
printf("%u %u %u %u %u", arr, &p, p, *p, **p);
arr is the array itself. When the array name is used in an expression like this, it decays to a pointer to the first element, so you get the address of that element.
&p is the address where the array pointer is stored. The only reason why you see this as the same address as the others is because you are running optimized code. Disable optimizations or declare p as static volatile and you'll see a change.
p is the address of the array, which will of course be the same as the address of the first element.
*p gives you an array type, which then decays into a pointer to the first element. This is identical to arr.
**p gives you the contents of the first element in the array.
p++ will increase the pointer by the rules of pointer arithmetic. Thus the address that p points at will be increased by the size of what it points at, which is an array of 4 ints, each 4 bytes large (assuming 32 bit). Therefore p will now point outside valid memory and anything will happen if you try to access it.
Somebody told me as an answer to my last question that
char *name[] = {"xxx", "yyy"}
is changed by the compiler to
char *name[] = {Some_Pointer, Some_Other_Pointer};
I tried the following for understanding:
printf("%p\n", &name);
printf("%p\n", name);
printf("%s\n", *name);
printf("%c\n", **name);
So as an output it gives me:
0xfff0000f0
0xfff0000f0
xxx
x
Can you explain to me how the address of the pointer "name" is the same as the address where the pointer "name" is pointing to?
From my understanding the pointer "name" itself occupies 8 bytes. How can the first string "xxx" which occupies 4 bytes in memory be at the same location as the pointer?
First of all, when you have any array like name in C, the value of the array is the address of its first element. Note that this value is not stored in some variable. It is used as an immediate value in the compiled assembly code. So it doesn't makes sense to think about its address.
Second, since an array is stored in memory as a bunch of consecutive location, the address of the array is defined the address of the first element. So for any array A you have the following equality of addresses
&(A[0]) == A == &A
It doesn't change anything to that if you have array of pointer or whatever.
To view the address of "xxx" you should print printf("%p\n", name[0]); like this. Surely address of name and address of "xxx" wont be the same. Here name is array of pointer which holds the address of "xxx and yyy".
printf("%p\n", &name);
printf("%p\n", name);
printf("%p\n", name[0]); address of "xxx"
printf("%p\n", name[1]); address of "yyy"
Can you explain to me how the address of the pointer "name" is the same as the address where the pointer "name" is pointing to?
&name give you the address of the entire array of pointers (which holds the pointers to the strings XXX and YYY) and name will give you the pointer to its first element, i.e, XXX (after decay). Since the address of the first byte is said to be the address of the variable (array), the value of &name is same as that of name but both of &name and name are of different type.
The type of name decays from array of char* to pointer to char* and its value is the address of the first element of the array. The expression &name is of type pointer to char* [2] and its value is the address of the array which is the same as the address of the array's first element.
It seems that you misunderstood the representation of array in C. There isn't a "meta" object representing an array in C. An array in C consists only its elements in sequence. Thus applying operator & to the array name simply gets you the address of the array's first element (value-wise, not type-wise).
If you try writing:
char (*p)[2] = &name;
printf("%p", &p);
This prints out the address of a pointer to an array, and it will certainly be a different value than name and &name.
From my understanding the pointer "name" itself occupies 8 bytes. How
can the first string "xxx" which occupies 4 bytes in memory be at the
same location as the pointer?
That's because name is an array, not a pointer. A pointer is a variable which stores the address of another variable of the same type but an array is a contiguous blocks of memory bound to (referenced by) a single identifier. Basically, it's a different type. Please note that arrays are not first class objects in C - you can't pass an array to or return an array from a function.
The confusion arises because an array in many situations decays (implicitly converted) into a pointer to its first element. Some case where this happens are:
void f(char p[]); // p is a pointer, not an array
// This is exactly the same as
void f(char *p);
char s[] = {'h', 'e', 'l', 'l', 'o'};
f(s); // here s decays to a pointer to its first element
// another example
char t = "hello"[1]; // the string literal decays to a pointer to its first element
Here are some cases where an array stays an array(does not decay into a pointer):
char s[] = "hello";
char *t = "hello"; // string literal decays into a pointer
printf("%d", sizeof s); // prints 5
printf("%d", sizeof t); // prints 4 or 8 depending on the pointer size on the machine
printf("%d", sizeof *t); // prints 1
// taking your example
char *name[] = {"xxxx", "yyyy"}; // yet another case where string literals decay to a pointer
printf("%p", name); // name is an array but here decays to a pointer
printf("%p", &name); // &name is a pointer to an array of 2 pointers to characters
Though name, &name evaluate to the same value in the printf call, they are not the same type. To see the difference do this:
printf("%p", name + 1);
printf("%p", &name + 1);
printf("%d", *(&name + 1) - name); // prints the length of the array
To sum up, arrays and pointers are different types. Pointers store addresses, arrays store values of type they are defined to store. In some situations arrays evaluate to the address of its first element. That's where the similarity ends between arrays and pointers.
I am bit confused with respect to pointer to arrays and just normal pointer and how to access.
I have tried this...
int *ptr1, i;
int (*ptr2)[3];
int myArray[3] = {1, 1, 1};
int myArray1[5] = {1, 1, 1, 1, 1};
ptr1 = myArray;
ptr2 = myArray1;// compiles fine even though myArray1 contains 5 elements
// and ptr2 is pointing to array of 3 elements.
printf("%d",ptr2[3]); // prints some garbage.
Why this statement is printing garbage? What is the correct statement?
Can anyone explain?
We can also declare pointer to array as
int (*ptr)[]; // ptr is a pointer to array.
When you do
ptr2 = myArray1;
compiler will throw you a warning message. Look boss types are not compatible.
In some context Arrays decays into pointers. Warning message is because, when arrays decays into pointers, the decayed type is pointer. In this case, when you do
ptr1 = myArray;
myArray decays into int *.
But when you do,
ptr2 = myArray1;
myArray1 decays into pointer that is int *, but the type of ptr2 is int (*)[].
In order to avoid warning, you should say
ptr2 = &myArray1; //&myArray1 returns address of array and type is int(*)[].
Why this statement is printing garbage? What is the correct statement? Can anyone explain?
printf("%d",ptr2[3]);// prints some garbage.
Yes, But why? Lets see the correct statement first...(note that index should be less than 3)
printf("myArray1[%d] = %d\n", i, (*ptr2)[2]);
We have to use (*ptr2)[i] to print the array element. This is because, just by mentioning ptr2, we will get the address of the array (not the address of some int). and by de-referencing it (*ptr2) we will get the address of 0th element of the array.
Pointer ptr2 is pointer to int array of size three
ptr2 = myArray1; // you may getting warning for this
should be:
ptr2 = &myArray1; // use & operator
And
printf("%d", ptr2[3]);
should be:
printf("%d", (*ptr2)[2]); // index can't be 3 for three size array
// ^^^^^^^
Notice parenthesis around *ptr2 is needed as precedence of [] operator is higher then * dereference operator (whereas if you use pointer to int you don't need parentheses as in above code).
Read Inconsistency in using pointer to an array and address of an array directly I have explained both array to access array elements. (1) Using pointer to int (2) pointer to array
Whereas ptr1 = myArray; is just find, you can simply access array elements using ptr1[i] (not i values should be 0 to 4)
int (*ptr2)[3];
This signifies that (*ptr2) is the identifier which contains the location in memory of the beginning of an integer array. Or, rephrasing, that ptr2 is an address. That address contains a value. That value is itself the address of the beginning of an array of ints.
So when you write ptr2 = myArray1 you are basically saying "The address of my address holder is the address of the beginning of myArray1".
So when you go to print the value using ptr2[3] you are actually printing the value of the memory address of myArray1, incremented 3*sizeof(ptr2) units. Which is why it looks like garbage, it's some memory address.
What should be in the print statement is (*ptr2)[3] which means "Take the address of ptr2 and get the value stored at that address. Next, using that second address, increment it 3*sizeof(int) and get the value stored at that incremented address."
Arrays in C are nothing more than a contiguous region of allocated memory. Which is why saying:
int *x = malloc(3*sizeof(int));
Is the same as:
int x[3];
Since [] and * both dereference a pointer, if we wanted to access the second element of either array, we could write:
int value = x[1];
or
int value = *x+sizeof(int); // Since *x would be index 0
Two of the major differences are that the [] notation is a bit easier to read but lengths must be determined at compile time. Whereas, with the *x/malloc() notation, we can dynamically create an array or arbitrary length.
I know that an array decays to a pointer, such that if one declared
char things[8];
and then later on used things somewhere else, things is a pointer to the first element in the array.
Also, from my understanding, if one declares
char moreThings[8][8];
then moreThings is not of type pointer to char but of type "array of pointers to char," because the decay only occurs once.
When moreThings is passed to a function (say with prototype void doThings(char thingsGoHere[8][8]) what is actually going on with the stack?
If moreThings is not of pointer type, then is this really still a pass-by-reference? I guess I always thought that moreThings still represented the base address of the multidimensional array. What if doThings took input thingsGoHere and itself passed it to another function?
Is the rule pretty much that unless one specifies an array input as const then the array will always be modifiable?
I know that the type checking stuff only happens at compile time, but I'm still confused about what technically counts as a pass by reference (i.e. is it only when arguments of type pointer are passed, or would array of pointers be a pass-by-reference as well?)
Sorry to be a little all over the place with this question, but because of my difficulty in understanding this it is hard to articulate a precise inquiry.
You got it slightly wrong: moreThings also decays to a pointer to the first element, but since it is an array of an array of chars, the first element is an "array of 8 chars". So the decayed pointer is of this type:
char (*p)[8] = moreThings;
The value of the pointer is of course the same as the value of &moreThings[0][0], i.e. of the first element of the first element, and also the same of &a, but the type is a different one in each case.
Here's an example if char a[N][3]:
+===========================+===========================+====
|+--------+--------+-------+|+--------+--------+-------+|
|| a[0,0] | a[0,1] | a[0,2]||| a[1,0] | a[1,1] | a[1,2]|| ...
|+--------+--------+-------+++--------+--------+-------++ ...
| a[0] | a[1] |
+===========================+===========================+====
a
^^^
||+-- &a[0,0]
|+-----&a[0]
+-------&a
&a: address of the entire array of arrays of chars, which is a char[N][3]
&a[0], same as a: address of the first element, which is itself a char[3]
&a[0][0]: address of the first element of the first element, which is a char
This demonstrates that different objects may have the same address, but if two objects have the same address and the same type, then they are the same object.
"ARRAY ADDRESS AND POINTERS TO MULTIDIMENSIONAL ARRAYS"
Lets we start with 1-D array first:
Declaration char a[8]; creates an array of 8 elements.
And here a is address of fist element but not address of array.
char* ptr = a; is correct expression as ptr is pointer to char and can address first element.
But the expression ptr = &a is wrong! Because ptr can't address an array.
&a means address of array. Really Value of a and &a are same but semantically both are different, One is address of char other is address of array of 8 chars.
char (*ptr2)[8]; Here ptr2 is pointer to an array of 8 chars, And this time
ptr2=&a is a valid expression.
Data-type of &a is char(*)[8] and type of a is char[8] that simply decays into char* in most operation e.g. char* ptr = a;
To understand better read: Difference between char *str and char str[] and how both stores in memory?
Second case,
Declaration char aa[8][8]; creates a 2-D array of 8x8 size.
Any 2-D array can also be viewed as 1-D array in which each array element is a 1-D array.
aa is address of first element that is an array of 8 chars. Expression ptr2 = aa is valid and correct.
If we declare as follows:
char (*ptr3)[8][8];
char ptr3 = &aa; //is a correct expression
Similarly,
moreThings in your declaration char moreThings[8][8]; contain address of fist element that is char array of 8 elements.
To understand better read: Difference between char* str[] and char str[][] and how both stores in memory?
It would be interesting to know:
morething is an address of 8 char array .
*morething is an address of first element that is &morething[0][0].
&morething is an address of 2-D array of 8 x 8.
And address values of all above three are same but semantically all different.
**morething is value of first element that is morething[0][0].
To understand better read: Difference between &str and str, when str is declared as char str[10]?
Further more,
void doThings(char thingsGoHere[8][8]) is nothing but void doThings(char (*thingsGoHere)[8]) and thus accepts any array that is two dimensional with the second dimension being 8.
About type of variables in C and C++: (I would like to add in answer)
Nothing is pass by reference in C its C++ concept. If its used in C that means author talking about pointer variable.
C supports pass by Address and pass by value.
C++ supports Pass by address, pass by value and also pass by Reference.
Read: pointer variables and reference variables
At the end,
Name Of an array is constant identifier not variable.
Nicely explained by Kerrek,
In addition to that, we can prove it by the following example:
#include <stdio.h>
int main ()
{
int a[10][10];
printf (".. %p %p\n", &a, &a+1);
printf (".. %p %p \n ", &a[0], &a[0]+1);
printf (".. %p %p \n ", &a[0][0], &a[0][0] +1);
}
The Output is :
.. 0x7fff6ae2ca5c 0x7fff6ae2cbec = 400 bytes difference
.. 0x7fff6ae2ca5c 0x7fff6ae2ca84 = 40 bytes difference
.. 0x7fff6ae2ca5c 0x7fff6ae2ca60 = 4 bytes difference.
&a +1 -> Moves the pointer by adding whole array size. ie: 400 bytes
&a[0] + 1 -> Moves the pointer by adding the size of column. ie: 40 bytes.
&a[0][0] +1 -> Moves the pointer by adding the size of element ie: 4 bytes.
[ int size is 4 bytes ]
Hope this helps. :)
OK, I'm having trouble understanding pointers to pointers vs pointers to arrays.
Consider the following code:
char s[] = "Hello, World";
char (*p1)[] = &s;
char **p2 = &s;
printf("%c\n", **p1); /* Works */
printf("%c\n", **p2); /* Segmentation fault */
Why does the first printf work, while the second one doesn't?
From what I understand, 's' is a pointer to the first element of the array (that is, 'H').
So declaring p2 as char** means that it is a pointer to a pointer to a char. Making it point to 's' should be legal, since 's' is a pointer to a char. And thus dereferencing it (i.e. **p2) should give 'H'. But it doesn't!
Your misunderstand lies in what s is. It is not a pointer: it is an array.
Now in most contexts, s evaluates to a pointer to the first element of the array: equivalent to &s[0], a pointer to that 'H'. The important thing here though is that that pointer value you get when evaluating s is a temporary, ephemeral value - just like &s[0].
Because that pointer isn't a permanent object (it's not actually what's stored in s), you can't make a pointer-to-pointer point at it. To use a pointer-to-pointer, you must have a real pointer object to point to - for example, the following is OK:
char *p = s;
char **p2 = &p;
If you evaluate *p2, you're telling the compiler to load the thing that p2 points to and treat it as a pointer-to-char. That's fine when p2 does actually point at a pointer-to-char; but when you do char **p2 = &s;, the thing that p2 points to isn't a pointer at all - it's an array (in this case, it's a block of 13 chars).
From what I understand, 's' is a pointer to the first element of the array
No, s is an array. It can be reduced to a pointer to an array, but until such time, it is an array. A pointer to an array becomes a pointer to the first element of the array. (yeah, it's kinda confusing.)
char (*p1)[] = &s;
This is allowed, it's a pointer to an array, assigned the address of an array. It points to the first element of s.
char **p2 = &s;
That makes a pointer to a pointer and assigns it the address of the array. You assign it a pointer to the first element of s (a char), when it thinks it's a pointer to a pointer to one or more chars. Dereferencing this is undefined behavior. (segfault in your case)
The proof that they are different lies in sizeof(char[1000]) (returns size of 1000 chars, not the size of a pointer), and functions like this:
template<int length>
void function(char (&arr)[length]) {}
which will compile when given an array, but not a pointer.
Here's the sample that works, plus printouts of pointer addresses to make things simple to see:
#include <stdio.h>
char s[] = "Hello, World";
char (*p1)[] = &s;
char *p2 = (char*)&s;
int main(void)
{
printf("%x %x %x\n", s, p2, *p2);
printf("%x\n", &s); // Note that `s` and `&s` give the same value
printf("%x\n", &s[0]);
printf("%c\n", **p1);
printf("%c\n", *p2);
}