Output from *++p and ++*p pointers - c

I don't understand why I am getting the output 1, 2, 3 for the below code. I believe it should be 1, 2, 2. What is the reason for the first output?
Also, let me point out that there are other questions that pertain to this kind of pointer arithmetic and dereferencing, but the answers to those questions suggest that the output should be 1, 2, 2.
int main()
{
int p[3] = {1,2,3};
int *q = p;
printf("%d\n", *q);
printf("%d\n", *++q);
int x = ++*q;
printf("%d\n", *q);
}

int p[3] = {1,2,3};
int *q = p;
printf("%d\n", *q);
q points to the 1. element, the above prints 1
printf("%d\n", *++q);
q points to the 2. element, the above prints 2.
int x = ++*q;
The 2. element is incremented from 2 to 3.
printf("%d\n", *q);
q points to the 2. element, the above prints 3.

*++q is parsed as *(++q); the result of ++q (which is q + 1) is dereferenced, and as a side effect q is incremented,
++*q is parsed as ++(*q); the result of *q (which is 2) is the operand of ++, which yields 3. As a side effect, *q is incremented.
Remember that both postfix and prefix ++ have a result and a side effect' and that the side effect does not have to be applied immediately after the expression has been evaluated. IOW,
a = b++ * ++c;
will be evaluated as
a = b * (c + 1);
but b and c don't have to be updated until the next sequence point.

Hi,
int p[3] = {1,2,3};
int *q = p;
printf("%d\n", *q); // The output for this line is 1
printf("%d\n", *++q); // Pre Incrementing the 1 which becomes 2
int x = ++*q;
// Here we are making the x point to same location as q and then we are
incrementing the location of the address q. Like q is pointing to the next location and so is the x.Hence the *q gives us 3 which is the value of the incremented location.
printf("%d\n", *q);
Hope it is helpful

Related

Operator and Pointer precedence

Below is the problem I found on the internet.
int main()
{
int a[4] = { 10, 21, 32, 43};
int *p = a + 3;
++*--p;
++*p--;
p[2] += p[1];
for (int i = 0; i < 4; ++i)
printf("%d - %d\t", a[i]);
return 0;
}
//What will be the output?
answer : 10 21 34 77
I understood a lot of things, but the only thing I'm stuck on:
What is the difference between (++*--p) and (++*p--) ?
Shouldn't these two give the same result? Because (*p--) and (*--p) give the same result in the compiler. The compiler I use is Code::Blocks
Because (*p--) and (*--p) give the same result in the compiler.
No, they do not. *p-- decrements p but applies * to the value of p before the decrement. *--p applies * to the value of p after the decrement.
What is the difference between (++*--p) and (++*p--) ?
++*--p decrements p and increments the object it points to after the decrement.
++*p-- decrements p but increments the object it points to before the decrement.
What is the difference between (++*--p) and (++*p--) ?
The difference is that --p decrements p and resolves to the new value of p, whereas p-- decrements p and resolves to the old value of p.
++* works identically on both - performing indirection on p, incrementing the value p points to, and resolving to this new value.
#include <stdio.h>
int main(void)
{
int a = 10;
int b = 10;
/* This prints 9, and `a` is now 9 */
printf("%d\n", --a);
/* This prints 10, and `b` is now 9 */
printf("%d\n", b--);
/* This prints 9 and 9 */
printf("%d %d\n", a, b);
}
Shouldn't these two give the same result? Because (*p--) and (*--p) give the same result in the compiler.
The order here matters, using (*--p) before (*p--) would resolve to the same element twice. Using (*p--) before (*--p) resolves to different elements.
#include <stdio.h>
int main(void)
{
int a[8] = { 1, 2, 3, 4, 5, 6, 7, 8 };
int *p = a + 4;
/* 4 then 4 */
printf("%d ", *--p);
printf("%d\n", *p--);
p = a + 4;
/* 5 then 3 */
printf("%d ", *p--);
printf("%d\n", *--p);
}

In which precedence is this statement evaluated?

++*P--;
That is a question from an exam, if P a pointer to any element in an array, explain what this statement really does.
I even wrote a simple code to evaluate it:
int i;
int* array = calloc(10, sizeof(int));
for (i = 0; i < 10; i++) {
array[i] = i;
printf("%d,", array[i]);
}
int* P = array + 5;
printf("\n %p", P);
printf("\n %d", *P);
++*P--;
printf("\n %p", P);
printf("\n %d \n", *P);
for (i = 0; i < 10; i++) {
printf("%d,", array[i]);
}
But the output confuses me even more:
0,1,2,3,4,5,6,7,8,9,
0x100105534
5
0x100105530
4
0,1,2,3,4,6,6,7,8,9,
It looks like it first dereferences P, then increases its value and then decreases value of pointer P, but why?
According to K&R table 2-1 from p53 (see the picture below)
++, --, and * (dereference) has the same precedence and associativity from right to left.
So first step should be decreasing value of P, then dereference and then increasing dereferenced value, am I wrong?
You are correct that the precedence is
++(*(P--))
But note that the decrement is a postfix operation: even though the change to P happens first, the rest of the expression uses the old value of P. So in your example, first P is decremented to array+4, but the value of P-- is array+5, so array[5] gets incremented.
You can imagine this expression
++*P--
the following way
int *tmp = p;
--p;
int value = *tmp;
++value;
Here is a demonstrative program
#include <stdio.h>
int main( void )
{
char s[] = "Hello World";
char *p = s + 6;
std::printf( "%c\n", ++*p-- );
std::printf( "%s\n", s );
p = s + 6;
char *tmp = p--;
char value = *tmp;
++value;
std::printf( "%c\n", value );
std::printf( "%s\n", s );
}
The program output is
X
Hello Xorld
Y
Hello Xorld
The difference in the outputting the string is that expression ++*p-- changes the string itself but expression ++value; changes a separate object. But the logic is similar.
Postfix expression p-- has the highest priority but its value is the value of p before decreasing.
Unary operators ++ and * in expression ++*p-- group right to left. So at first operator * is applied to the expression and after that operator ++ is applied.

Printing pointer value with increment of the address in C

#include <stdio.h>
#include <stdlib.h>
int main()
{
int k,*ptr=NULL;
int arr[]={1,2,3,4,5,6,7,8,9,10};
ptr=arr;
printf("%d ",*ptr++);
printf("%d ",*(ptr++));
printf("%d ",(*ptr)++);
printf("%d ",*++ptr);
printf("%d ",++*ptr);
}
Why does the second printf print the number 2 ? It should print 3.
As everyone else said, the distinction is between pre-incrementing (where the increment occurs before the value is fetched) and post-incrementing (where the value is fetched and then the increment occurs). The value 2 should be printed, of course.
Maybe this assertion-laden code will help. The assert() macro stops the program if the condition specified is false when it is executed. The assertions do not fire.
The assertions show how the value of ptr changes, and also how the values in the array change.
#include <assert.h>
#include <stdio.h>
int main(void)
{
int arr[] = {1,2,3,4,5,6,7,8,9,10};
int *ptr = arr;
assert(ptr == &arr[0]);
printf("%d\n",*ptr++); // print 1; ptr = &arr[1]
assert(ptr == &arr[1]);
printf("%d\n",*(ptr++)); // print 2; ptr = &arr[2]
assert(ptr == &arr[2]);
assert(*ptr == 3);
printf("%d\n",(*ptr)++); // print 3; ptr = &arr[2]; arr[2] = 4
assert(ptr == &arr[2]);
assert(*ptr == 4);
printf("%d\n",*++ptr); // print 4; ptr = &arr[3]
assert(ptr == &arr[3]);
assert(*ptr == 4);
printf("%d\n",++*ptr); // print 5; ptr = &arr[3]; arr[3] = 5
assert(ptr == &arr[3]);
assert(*ptr == 5);
printf("Offset: %d\n", (int)(ptr - arr));
for (int i = 0; i < 9; i++)
printf("a[%d] = %d\n", i, arr[i]);
return 0;
}
Output:
1
2
3
4
5
Offset: 3
a[0] = 1
a[1] = 2
a[2] = 4
a[3] = 5
a[4] = 5
a[5] = 6
a[6] = 7
a[7] = 8
a[8] = 9
post increment operator increments the variabl after accessing the value.
So, after getting *ptr, which is 2, ptr increases itself.
Not, because ptr++ return the value BEFORE the incrementation, so the value is 2.
*ptr++ first dereferences the pointer which gives 2, then increments the pointer
The expression *(ptr++) is a post increment expression so the value of of that expression is ptr and then it is incremented. So the result of the expression is that it still points to the 2
the * operator applies to the result of p++, which is the value of original p (prior to the increment). So it prints 2. I you want 3 to be printed you should do (++p) which returns the incremented value.
It should print 2, because the postfix operator ++ first returns the value and then increments it.
The fact that you added brackets around it (*(ptr++)) does not influence the increment.
The value will be incremented after the whole line.
Looking at disassembly might help you to see what happens at that line.
The *ptr++ returns the value at ptr and then increments it,so in the second printf() statement it only returns 2 and then increments it to 3.

Pointers manipulation in c

I have a doubt in pointers manipulation...
main()
{ int x=10; // extra line added...
char *p=x;
printf("%d", &p)
printf("%d", &p[0]);
printf("%d" , &p[1]);
}
This code gives output
Address of 10..
10
11
how are the last two outputs are coming.. Can anyone explain it to me ..?
Code changed.....
This is Undefined Behavior.
The pointer needs to point to something valid before some value can be added to that location.
char a = 10;
char *p = &a;
Will explain two scenarios:
Scenario 1: char * p = x;
x == 10, p is a char pointer which is initialized with 10 (an address which user program can't access): p == 10
The value of p (ie, *p) will lead to segmentation fault (being invalid memory reference)
p[0] == *(p + 0) and &p[0] == (p+0) == p which is 10.
Hence printf("%p", &p[0]) will give you 10.
p[1] == *(p + 1) and &p[1] == (p+1)
Since, p is a character pointer, it gets increments by sizeof(char), ie 1
Hence printf("%p", &p[1]) will give you 10+1 = 11
Scenario 2: char * p = &x;
Here p is a char pointer pointing to integer x
Value of x = 10
Address of x = 1000 (assume)
Hence p = 1000
p[0] == *(p + 0) and &p[0] == (p+0) == p
Hence printf("%p", &p[0]) will give you 1000
p[1] == *(p + 1) and &p[1] == (p+1)
Since, p is a character pointer, it gets increments by sizeof(char), ie 1
ie &p[1] == 1000+1 == 1001
p and &p[0] will be evaluated to same address (address of first element of array) which is 10.
So &p[0] will be evaluated to 10 and &p[1] to &p[0] + sizeof(char) which is 11
Your code will most likely segfault though when you dereference p (*p).
Following code will always print True.
main()
{
int* p;
printf("%s\n",p == &p[0] ? "True" : "False");
}
Some errors in your code:
int x = 10;
char * p = &x; // error 1 - you was assigning int to pointer
printf("%p\n", &p); // error 2 - you printing address of pointer (char **),
// so different format string is needed
printf("%p\n", &p[0]); // same error 2 - printing address of first byte in int x
printf("%p\n" , &p[1]); // same error 2 - printing address of second byte in int x
printf("%d", &p[0]);
printf("%d" , &p[1]);
it will print out the address that p is pointered on..
because char *p=x; while x = 10;
then ,, &p[0] = 10, &p[1] = 11 &p[2] = 12 , and so on..
printf("%d", &p);
I'm not so sure about this, but as i know it will print out the value contained in memory 10 in my case = 10000
printf("%d", p);
it will print out the 10, which is the *p value;
cmiiw
char *p=10;
The code at present has undefined behavior. Pointer p is not pointing to any valid memory location to initialize 10 in that location.
With that said, both p, &p[0] yields the same memory location.

What's the difference between *d++ and (*d)++ in C?

as in the title, what's the difference because these two seem to get me the same results?
No they are not the same. Assume that d is a pointer to int:
int n = 0;
int* d = &n;
*d++; // d++ then *d, but d++ is applied after the statement.
(*d)++; // == n++, just add one to the place where d points to.
I think there is an example in K&R where we need to copy a c-string to another:
char* first = "hello world!";
char* second = malloc(strlen(first)+1);
....
while(*second++ = *first++)
{
// nothing goes here :)
}
The code is simple, put the character pointed by first into the character pointed by second, then increment both pointers after the expression. Of course when the last character is copied which is '\0', the expression results to false and it stops!
The increment ++ has higher operator precedence than the dereference *, so *d++ increments the pointer d to point to the next location within the array, but the result of ++ is the original pointer d, so *d returns the original element being pointed to. Conversely, (*d)++ just increments the value being pointed to.
Example:
// Case 1
int array[2] = {1, 2};
int *d = &array[0];
int x = *d++;
assert(x == 1 && d == &array[1]); // x gets the first element, d points to the second
// Case 2
int array[2] = {1, 2};
int *d = &array[0];
int x = (*d)++;
assert(x == 1 && d == &array[0] && array[0] == 2);
// array[0] gets incremented, d still points there, but x receives old value
In the official C terminology, these expressions do give you the same results, as they should. In the proper terminology, the "result" of a non-void expression is what that expression evaluates to. Both of your expressions evaluate to the initial value of *d, so not surprisingly, the results are the same.
However, an addition to a "result" every expression in C has zero or more so called "side effects". And side effects of these two expressions are completely different. The first expression increments the value of pointer 'd'. The second expression increments the value of '*d' (the pointed value).
The first increments the pointer, the second increments the value pointed to.
As an experiment, try this:
int main() {
int x = 20;
int *d = &x;
printf("d = %p\n", d);
int z = (*d)++;
printf("z = %d\n", z);
printf("d = %p\n", d);
int y = *d++;
printf("y = %d\n", y);
printf("d = %p\n", d);
}
They do return the same result, but the state change in your program is completely different.
This is easiest to understand if we just expand out the operations.
x = *d++;
// same as
x = *d;
d += 1; // remember that pointers increment by the size of the thing they point to
x = (*d)++;
// same as
x = *d;
*d += 1; // unless *d is also a pointer, this will likely really just add 1
I don't have a compiler handy.
a = (*d)++;
b = (*d);
is a==b? i don't think it is.

Resources