Why does the following piece
char *arr[] = {"C", "C++", "Java", "VBA"};
char *(*ptr)[4] = &arr;
printf("%s\n", ++(*ptr)[2]);
printf("%s\n", ++(*ptr)[2]);
printf("%s\n", ++(*ptr)[2]);
outputs
ava
va
a
I can't figure out why and where the information that dereferenced ptr is incremented is kept. Debugger tells me that (*ptr)[2] is indeed incremented, and ptr stays unchanged, but I don't know how to explain it.
The array subscript operator [] has higher precedence than the preincrement operator ++. So the expression is effectively:
++((*ptr)[2])
As for where the increment is stored, your array arr is an array of pointers, each pointing to a string literal. When you increment (*ptr)[2] the value of this pointer is incremented by 1, so it points to the next character in the string literal.
Ptr is a pointer to array. &a is pointing to address of whole array, so when you do &a+1 whole size of array gets incremented.
Now, when we do *ptr, it means now it is pointng to first element of array i.e. ptr contains the address of 1st element of array i.e. 1000 .
Now, [ ] operator increments the address to that location, so (*ptr)[2] is equivalent to 1000 +2 (pointer addition) i.e. 1008 .
Now we are at 1008 location and applying ++, so this will act on its memory that contain the address 300, will become 301 (because JAVA is string that each element in string takes 1 byte space in memory, so character pointer gets incremented 1 byte only.), so it prints the "ava" . Now, apply same with other calls.
Related
I was asked this question as a class exercise:
int A[] = {1,3,5,7,9,0,2,4,6};
printf("%d\n", *(A+A[1]-*A));
I couldn't figure it out on paper, so went ahead to compiling a simple program and tested it and found that printf("%d",*A) always gives me 1 for the output.
But I still do not understand why this is the case, hence it would be great if someone can explain this.
A is treated like a pointer to the first element of array of integers.
A[1] is the value of the first element of that array, which is 3 (indexes are 0-based)
*A is the value to which A points, which if the zeroth element of array, so 1.
So
A[1] - *A == 3 - 1 == 2
Now we have
*(A + 2)
That's where pointer arithmetic kicks in. Since A is a pointer to integer, A+2 points to the second (0-based) item in that array and *(A+2) gets its value.
So answer is 5.
Also please note for future reference that pointer to an integer and array of integers are somewhat different things in C, but for the purposes of this discussion they are the same thing.
Break it down into its constituent parts:
A by itself is the memory address of the array, which is also equivalent to &A[0], the memory address of the first element of the array.
A[1] is the value stored in the second element of the array, which is 3.
*A dereferences the memory address of the array, which is equivilent to A[0], the value stored in the first element of the array, which is 1.
So, do some substitutions:
*(A+A[1]-*A)
= *(A+(A[1])-(A[0]))
= *(A+3-1)
= *(A+2)
The notation *(Array+index) is the same as the notation Array[index]. Under the hood, they both take the starting address of the array, increment it by the number of bytes of the array element type (in this case, int) multiplied by the index, and then dereference the resulting address. So *(A+2) is the same as A[2], which is 5.
Arrays used in expressions are automatically converted into pointers pointing at the first elements of the arrays except for some exceptions such as operands of sizeof or unary & operators.
E1[E2] is defined to be equivalent to *((E1) + (E2))
+ and - operator used to pointers will move the pointer forward and backward.
In this case, *A is equivalent to *(A + 0), which is equivalent to A[0] and it will give you the first element of the array.
The expression *(A+A[1]-*A) will
Get the pointer to the first element, which points at 1, via A
Move the pointer to A[1] (3) elements ahead via +A[1], so the pointer now points at 7
Move the pointer to *A (1) element before what is pointed via -*A, so the pointer now points at 5
Dereference the pointer via the unary * operator, so the expression is evaluated to 5
An array variable in C is only the pointer to the initial memory location for the array. So if you derreference the array, you will always get the value for the first position.
If you sum up 1 to the original array value, like *(A+1) you will get the second position.
You can get any position from the array using the same method:
*(A) is the first position
*(A+1) is the second position
*(A+2) is the third position
and so on...
If you declare the int array as int* A and allocate the memory and attribute the values, it is usually easier to visualize how this works.
I was writing this program -
#include<stdio.h>
void main()
{
int arr[20];
arr[0]=22;
arr[1]=23;
int (*p)[20]=&arr;
printf("address in p :%u:\n",p);
printf("address in *p:%u:\n",*p);
}
The Output of this code is same for p and *p ! So far as I know *p is holding the base address of arr which is nothing but arr[0]!!!
So *p should have give the output 22 ! But it's showing the same memory address like p is showing. Please tell me why this is happened? What is the reason behind it.
Codepad Site Link : http://codepad.org/LK7qXaqt
p is a pointer to an array of 20 integers. Address of first byte of array is said to be the address of the array. Dereferencing it will give the entire array itself. Therefore *p represents the array arr, so you can think of *p as an array name.
As array names are converted to pointers to its first element when passed to a function, *p is decayed to pointer to first element of arr. Therefore
printf("address in *p: %p:\n", (void*)*p);
will print the address of first element of array arr while
printf("address in p: %p:\n", (void*)p);
will print the address of the entire array (i.e first byte of the array). Since value of first byte and first element is same, that's why both are printing the same address.
For detailed explanation: What exactly is the array name in c?
Because p and *p points to same memory location only there types are different
+-+-+-+-+-+-+-+-+-+-+-+-+
| | | | | | | | | | | | |
+-+-+-+-+-+-+-+-+-+-+-+-+
arr [ ]
p [ ]
(*p)[ ]
If you print p+1 and *p + 1 you should see the difference
int (*p)[20] declare p as pointer to array of size 20 of type int so at the same time *p is the pointer to the first element of the array.
Address of first element and of whole array would be same.
Yes it is possible to apply the address operator to an array, although it seems redundant. The result p is a pointer to array. Such a thing is under normal circumstances rarely encountered. As #Mohit pointed out correctly, the object it points to is the whole array, which implies that sizeof(*p) should be the size of the array (not of its first element).
*p logically is the array then; as usual it decays to a pointer to its first element (which is an int) when passed as an argument, e.g. to printf. Since it's the first element its location in memory is the location of (the beginning of) the whole array.
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.
I cannot figure this out. Perhaps it is because it's 2am. At any rate, I am at a loss here.
#include <stdio.h>
int main()
{
char array[] = "123456789";
char* ptr = array;
printf("%c\n", *(ptr++));
printf("%c\n", *ptr);
*ptr = array[3];
printf("%c\n", *(ptr++));
printf("%c\n\n", *ptr);
return 0;
}
The result is:
1
2
4
3
I have a pointer, which I assign to array.
I then print, what I thought would be the first index ( '2' ), but instead get 1.
-- So, I assume that *(ptr++) actually dereferences, before it increments the pointers.
Then I reassign ptr the 4th index ( '4' ) and repeat step 2. This works as expected now that
I see C does not calculate the parenthesis first before dereferencing.
Then I print the newly incremented ptr to display ( '5' ) ... and I get 3?
How is that, step 1&2 and 3&4 are identical, but I get different results?
Let's go through the code step-by-step:
Step 0:
char* ptr = array;
Point the char pointer to the start of array (namely position 0).
Step 1:
printf("%c\n", *(ptr++));
Dereference the pointer at position 0, print the value residing there (1) and then increment the pointer to position 1
Step 2:
printf("%c\n", *ptr);
Dereference the pointer at position 1 and print the value residing there (2)
Step 3:
*ptr = arr[3];
Dereference the pointer at position 1 and update the value pointed to with the value at position 3 of the array. This is value 4.
Step 4:
printf("%c\n\n", *(ptr++));
Dereference the pointer at position 1, print the value we just updated (4) and then increment the pointer to position 2
Step 5:
printf("%c\n", *ptr);
Dereference the pointer at position 2 and print the value there (3).
Perhaps what you actually intended is to have ptr = &arr[3]; which will assign the pointer to a new position (namely the address of arr[3]).
Note that the braces around ptr in the above are actually redundant due to operator precedence.
For the case of *(ptr++), post-increment has higher precedence than indirection therefore it will be applied before we dereference the pointer
Braces are also unnecessary around *(++ptr) too. Here even though pre-increment and indirection have the same precedence, they are evaluated right-to-left. And so the pointer will be incremented before it is dereferenced.
Try this instead:
ptr = array + 3;
*(ptr++) advances the pointer after dereferencing. If you want it to get the 2nd value in the array, use *(++ptr).
You're assigning a value to the pointer's value. In effect, you are changing the pointer (pointing to the second element) to point to 4. You're not really changing the pointer location at all. So you are still printing the 2nd element, except it now has a value of 4.
You advance to the 3rd element, printing 3.
ptr++ is post-increment operator, so the pointer increments AFTER it dereference it (according to the standard).
Besides, the step:
*ptr = array[3];
assigns to the array[1] value 4, so you print 4 instead of 2 and increment to the 3.
The correct way of pointer assignment is:
ptr = &array[3];
or
ptr = (array + 3);
You are actually assigning the value of array[3] to the value pointet by ptr.
In the below two lines,
char a[5]={1,2,3,4,5};
char *ptr=(char *)(&a+1);
printf("%d",*(ptr-1));
This prints 5 on screen.Whereas when use a instead of &a,
char a[5]={1,2,3,4,5};
char *ptr=(char *)(a+1);
printf("%d",*(ptr-1));
This prints 1
Both a and &a are the starting address of the array.So Why is this difference?
Also
char *ptr=&a+1;
shows a warning.
Arrays aren't pointers! Read section 6 of the comp.lang.c FAQ for more information.
Let's look at your second case first, since it's the more "normal" and idiomatic looking. Line by line:
You declare an array a containing 5 char elements.
The name of the array (a) decays into a pointer to its first element in this context. You add 1 to that and assign the result to ptr. ptr points to the 2. No cast is necessary, though you have one.
You subtract 1 from ptr and then dereference and print - hence you get the 1.
Now, let's address the first case, again line by line:
You declare an array a containing 5 char elements.
You take the address of a, yielding a char (*)[5] type pointer. You then add 1 to this pointer - because of pointer arithmetic this new pointer pasts to the byte just after 5 in memory. Then you typecast (required, this time) and assign this value to ptr.
You subtract 1 from ptr and then dreference and print. ptr is a char *, so this subtraction simply moves the pointer back by one from "one past the end of a" to point to the last element of a. Hence you get the 5.
Finally, the reason char *ptr=&a+1; gives a warning is because C requires conversions between pointer types to have an explicit cast. As mentioned above, &a is of type char (*)[5], not char *, so to assign that value to a char * variable, you'll need the explicit cast.
Since you seem totally new to it let me explain it to you in simple terms instead of going for the rigorous explanation.
You see, for your program above, a and &a will have the same numerical value,and I believe that's where your whole confusion lies.You may wonder that if they are the same,the following should give the next address after a in both cases,going by pointer arithmetic:
(&a+1) and (a+1)
But it's not so!!Base address of an array (a here) and Address of an array are not same! a and &a might be same numerically ,but they are not the same type. a is of type char* while &a is of type char (*)[5],ie , &a is a pointer to (address of ) and array of size 5.But a as you know is the address of the first element of the array.Numerically they are the same as you can see from the illustration using ^ below.
But when you increment these two pointers/addresses, ie as (a+1) and (&a+1), the arithmetic is totally different.While in the first case it "jumps" to the address of the next element in the array, in the latter case it jumps by 5 elements as that's what the size of an array of 5 elements is!.Got it now?
1 2 3 4 5
^ // ^ stands at &a
1 2 3 4 5
^ // ^ stands at (&a+1)
1 2 3 4 5
^ //^ stands at a
1 2 3 4 5
^ // ^ stands at (a+1)
The following will give an error about unspecified bound for array as not explicitly specifying the size as below means the program won't know how many elements to "jump" to when something like (&a+1) is encountered.
char a[]={1,2,3,4,5};
char *ptr=(char *)(&a+1); //(&a+1) gives error as array size not specified.
Now to the part where you decrement the pointers/addresses as (ptr-1).In the first case, before you come to the decrement part, you should know what happens in the statement above it where it is cast to type char*:
char *ptr=(char *)(&a+1);
What happens here is that you "strip off" the original type of (&a+1) which was type char (*)[5] and now cast it to type char* which is the same as that of a,ie, the base address of the array.(Note again the difference between base address of an array and address of an array.So after the cast and assignment in the above statement,followed by the decrement in printf(), ptr now gives the memory location right after the last element of the array, which is 5.
1 2 3 4 5
^ // ^ stands at location of 5, so *ptr gives 5
So when you dereference the pointer ptr after decrementing it as *(ptr-1) it prints the value of 5 as expected.
Now finally, contrast it with the second case where 1 is printed.Look at the illustration I have given using the symbol ^. When you had incremented a as a+1, it points to the second element of the array, ie 2 and you had assigned this address to ptr.So when you decrement ptr it as (ptr-1), it jumps back one element and now points to the first element of the array ,ie 1.So dereferencing ptr in second case gives 1.
1 2 3 4 5
^ // ^ stands at address of 1, so *ptr gives 1
Hope this made it all clear.
The difference is in the type of the pointer that you get:
Array name a by itself represents a pointer to the initial element of the array. When interpreted in that way, e.g. in an expression a+1, the pointer is considered to point to a single character.
When you take &a, on the other hand, the pointer points to an array of five characters.
When you add an integer to a pointer, the number of bytes the pointer is moved is determined by the type of the object pointer to by the pointer. In case the pointer points to char, adding N advances the pointer by N bytes. In case the pointer points to an array of five chars, adding N advances the pointer by 5*N bytes.
That's precisely the difference that you are getting: your first example advances the pointer to the element one past the end of the array (which is legal), and then move it back to the last element. Your second example, on the other hand, advances the pointer to the second element, and then moves it back to point to the initial element of the array.
What you are running into is a subtlety of pointer arithmetic.
The compiler treats "a" as a pointer to char - an entity that is 1 byte in size. Adding 1 to this yields a pointer that is incremented by the size of the entity (i.e. 1).
The compiler treats "&a" as a pointer to an array of chars - an entity that is 5 bytes in size. Adding 1 to this yields a pointer that is incremented by the size of the entity (i.e. 5).
This is how pointer arithmetic works. Adding one to a pointer increments it by the size of the type that it is a pointer to.
The funny thing, of course, is that when it comes to evaluating the value of "a" or "&a", when dereferencing, they both evaluate to the same address. Which is why you see the values that you do.
Arrays "decay" into pointers to the first element. So taking the address of a gives you a pointer to an array of 5 chars, which is like declaring a char[][5]. And incrementing this pointer advances to the next element of the char[][5] array - that is 5 characters at a time. This is different from incrementing the pointer that decays from the char[5] array - that is, one character at a time.