Can't Understand this simple code output - c

Code:
int a = 5;
int *ptr;
ptr = &a;
printf("%d",*ptr);
printf("\n%d",*(ptr++));
printf("\n%d",(*ptr)++);
printf("\n%d",++(*ptr));
Output:
5
5
1638268
1638268
and I am expecting the output to be:
5
junk
5
7
Sory, my pointer and operator precedence concept is very bleak. Can't understand this simple ouput.

The first is obviously 5, just dereferencing a pointer
Still five because the postfix operator returns the pointer preincrement
3 and 4 are junk because the pointer no longer points to memory that has been assigned
If you want the second to act like you expected and print junk you can use the prefix ++ instead

int a = 5;
int *ptr;
ptr = &a;
printf("%d",*ptr); // 5 as you expected.
printf("\n%d",*(ptr++)); // 5, because the pointer is incremented after this line
printf("\n%d",(*ptr)++); // Not 5 because pointer points to another location.
printf("\n%d",++(*ptr)); // Pointer already changed, no longer pointing at 5.

int a = 5;
int *ptr;
ptr = &a; // ptr is the address of the int 5
printf("%d",*ptr); // dereferences ptr, which points to in 5
printf("\n%d",*(ptr++)); // increments ptr by one, so ptr not points to
// an int one over from wherever int 5 is in memory
// but return ptr before incrementing and then dereference it
// giving int 5
printf("\n%d",(*ptr)++); // dereference ptr, which is now one int over from 5 thanks
// to the last line, which is garbage, try
// to increment garbage by 1 after printing
printf("\n%d",++(*ptr)); // dereference ptr, which is now one int over from 5,
// try to increment garbage by one before printing

*ptr just gives the value at the location which is nothing but value of a.
*(ptr++) is equivalent to (*ptr) and then (ptr += 1) because of post increment, so first it gives the value which is used by printf and then increments the pointer so now it is pointing to junk memory .
(*ptr)++ is equivalent to (*ptr) and then (*ptr += 1), so it takes the value at junk memory and increments it.
++(*ptr) is equivalent to (*ptr) += 1 so it increments the value at the junk location, now you can see the effect of undefined behavior so you don't get the last incremented value plus one, but got the same value as the last one because of undefined behavior. On my compiler I got the last incremented value plus one.

Related

Having difficulty in understanding of pointer to pointer increment value

Refer the following C program and while incrementing the pointer (i.e. p), it is correctly incrementing by 4 bytes. While if I try to increment the pointer to pointer (i.e. pp), then same is incrementing by 8 bytes. And I am not understanding why is it happening in this way and may be i have misunderstanding in the concept.
#include <stdio.h>
int main()
{
float a = 5, *p, **pp;
p = &a;
pp = &p;
printf("a=%f, p=%p, pp=%p\n", a, p, pp);
a = a + 1;
p = p + 1;
pp = pp + 1;
printf("a=%f, p=%p, pp=%p\n", a, p, pp);
return 0;
}
output:
a=5.000000, p=0x7ffc93c93374, pp=0x7ffc93c93368
a=6.000000, p=0x7ffc93c93378, pp=0x7ffc93c93370
Pointer arithmetic is done in units of the size of the type that the pointer points to. On your system, sizeof(float) is 4, so incrementing p adds 4 bytes to it. But sizeof(float*) is 8 because it's a 64-bit system, so incrementing pp adds 8 bytes to it.
To append the answer of #Barmar I would like to point out that if you have an array
T a[N];
where T is some type and N is some value then after such a declaration of a pointer like
T *p = a;
The pointer p will point to the first element of the array a. This declaration is equivalent to
T *p = &a[0];
If to increment the pointer p it is naturally to assume that it will point to the second element of the array a that is its value will be the value of the expression &a[1]. S0 you need to add to the original value of the pointer p the value that is equal to the value of the size of an element of the array a that is the value equal to sizeof( T ).
Such a calculation is named the pointer arithmetic.
Thus the expression
p + 1
or
++p
means to add the value sizeof( T ) to the value stored in the pointer p. As a result the pointer expression will point to the next element of the array.

Why can't I print the pointer value that has been initialized while declaring the pointer?

I initialized the pointer with a constant, and I knew its address will be delivered to the pointer. So when I tried to test whether the constant can be print or not, the program crashed. Is that illegal?
#include <stdio.h>
int main()
{
int *i = (int *)1;
printf("The value that i pointer points to is %d\n", *i);
return 0;
}
You seem to think (int *)1 produces the address where the value 1 is stored. It does not.
When a cast such as (int *) is used to convert an integer to a pointer, the result is generally that the value is made into an address.1
Thus int *i = (int *)1; sets i to point to the address 1. Then, when attempting to print *i, your program crashed because 1 was not a valid memory address. (Quite commonly, the first page of memory is kept unmapped so that incorrect uses of the null pointer will crash and reveal a problem rather than allowing the program to continue executing with incorrect data.)
To set i to point to an int with the value 1, you must set it to the address of an int object that has the value 1. One way to do this is:
int n = 1;
int *i = &n;
You can also create an unnamed int with the value 1 using a compound literal:
int *i = & (int) { 1 };
The (int) { 1 } creates a compound literal with the value 1, and the & takes its address, and then i is initialized to that address.
Footnote
1 According to the C standard, the result is implementation-defined. So a compiler could define any result it wants. However, every C compiler I have seen makes the integer value into an address, in one way or another. The resulting address is not necessarily valid to use for accessing an object.
(int *)1; is not a pointer to value 1. but rather the pointer to the memory cell # 1. What you probably want is
#include <stdio.h>
int main()
{
int n=1;
int *i = &n;
printf("The value that i pointer points to is %d\n", *i);
return 0;
}
printf("The value that i pointer points to is %d\n", *i);
You try to dereference the pointer i, but it's value (the value of the pointer) is some value, you set yourself. Can you guarantee that at address 0x0001 is an integer you own? All you can do with such a pointer is print it's pointer value (not the value it points to):
printf("The value of pointer i is %p\n", i);

Pointer to a 2D array

I have a 2D array (int s[4][2])and I created a pointer as int (*p)[2].
The pointer p is now assigned the address of 1st element of row within a for loop.
for (int i = 0; i<4; i++)
p = &s[i];
Now when I try to write the array elements data using dereferencing, I get wrong values.
printf ("%d \n", *p)
However, if I create another pointer and link that with the previous pointer
int *ptr = p;
and dereference pointer ptr I get correct values.
printf ("%d \n", *ptr)
When both the pointers are pointing to the same address why does one pointer (*ptr) work as expected and other (*p) does not return expected values?
If p is a pointer to array then *p is array of 2 ints (int[2]). So, you can't print an array element like this:
printf ("%d \n", *p);
To print the array elements through the pointer p, you need to do:
printf ("%d \n", (*p)[0]); /* first element */
printf ("%d \n", (*p)[1]); /* second element */
p is not a pointer to an int. It is a pointer to an array of two int. Therefore *p is also an array of two int. Since it is not an int, printing it using %d gives undefined behaviour.
You would not be able to "link" ptr to p because of a type mismatch (ptr is a pointer to int, and p (as already noted) is a pointer to an array of two int. Hence the assignment ptr = p would not compile. If you are forcing it to compile (e.g. ptr = (int *)p), then ptr and p will have the same value (i.e. they will identify the same location in memory) but different type (i.e. dereferencing them interprets the contents of that memory differently).
The value (ignoring type) of p will be the address of s[0][0]. Similarly, the value of ptr will be the address of s[0][0].
As a result printf("%d\n", *ptr) will print the value of s[0][0].
When both the pointers are pointing to the same address why does one pointer (*ptr) work as expected and other (*p) does not return expected values?
*p evaluates to an int[2], an array.
Passing an int[2], an array to a function, results in passing a pointer the array's 1st element, a int*.
*ptr evaluates to an int.
Passing an int to a function, results in passing an int to a function ... :-)
By
int (*ptr)[2] ; // means int[2]<-(*ptr)
You got pointer to an array of two integers
The pointer p is now assigned the address of 1st element of row
within a for loop.
This is not correct, technically p is assigned the address of the entire int[2] block (Hint : use sizeof to verify the size).
What is the problem with printf ("%d \n", *ptr)
*ptr by itself doesn't contain a integer but it holds the address of the first element of int[2] ie *ptr itself is a pointer.
A working example would be
int main(void)
{
int i;
int s[4][2]={{0,1},{2,3},{4,5},{6,7}};
int (*ptr)[2];
for(i=0;i<4;i++)
{
ptr=&s[i];
printf("i:%d\n",i);
printf("Element 1 : %d\n",(*ptr)[0]);
printf("Element 2 : %d\n",(*ptr)[1]);
/* Replacing (*ptr)[1] with *((*ptr)+1) gives you the same
* results
*/
}
return 0;
}
Output
i:0
Element 1 : 0
Element 2 : 1
i:1
Element 1 : 2
Element 2 : 3
i:2
Element 1 : 4
Element 2 : 5
i:3
Element 1 : 6
Element 2 : 7

postincrement pointers with arrays

Cannot understand why value of a[1] is not equal to 10
void main()
{
int a[]={2,1};
int *ptr=a;
*ptr++=10; //trying to update a[1]=10
printf("%d",*ptr);
}
Could someone pls explain this?
Let's take your code, and space it out some:
int main() {
int a[]={2,1};
int *ptr=a;
// Validation
assert(ptr == &a[0]);
// Let's now do what *ptr++ = 10 actually does:
*ptr = 10;
ptr = ptr + 1;
// Validation
assert(ptr == &a[1]);
// Printing. Note that we are printing a[1], not a[0].
printf("%d",*ptr);
}
It might also be helpful to read a quote from cppreference. They are discussing the difference between a postfix increment (ptr++) and a prefix increment (++ptr).
The returned result of the postfix version of the operator is the original operand, with a side-effect being that the operand is incremented/decremented after this result is returned.
The returned result of the prefix version of the operator is the incremented/decremented operand.
It sounds like you want to use a prefix increment, not a postfix increment.
Since ++ has higher precedence than unary *, *p++ is going to be grouped as *(p++) which means: Dereference the old ptr and increment ptr by 1 (as long as the original value is used, the increment can happen at any time). *ptr++=10; will update a[0] to 10.
Your code commented as execution flows:
int main(void)
{
int a[]={2,1}; //sets a[0]=2, a[1]=1
int *ptr=a; //sets *ptr == address of a, or a[0]
*ptr++=10; //sets a[0] = 10 (a[1] unchanged)
printf("%d",*ptr);
getchar();
}
*ptr++=10; assigns the value 10 to the address of a[0], then increments *ptr after that assignment is made.

why the address difference is getting printed (according to the pointer type)

#include<stdio.h>
int main()
{
int *p=0;
char *ch=0;
p++;
ch++;
printf ("%d and %d\n",p,ch);
return 0;
}
Output:
4 and 1
I know the char pointer increments as +1 in the address that it is pointing too.
I know the pointer to an int increments as +4 in the address in gcc that it is pointing too.
I know Derefrencing a pointer should be done by the use of * with the pointer.
Queries:
Why is this not giving any garbage value for p and ch as both are pointers and has not assigned any address;
Why is this giving me the address difference that the respective pointer has obtained while incrementing, or is this a undefined behavior.
3.Why is the output 4 and 1?
Pl. Explain.
I have compiled this code on gcc-4.3.4.
Its a C code.
I am sorry if this comes out to be a copy of some question as I was not able to find any such question on stackoverflow.
1.Why is this not giving any garbage value for p and ch as both are pointers and has not assigned any address;
err, you assigned address here > int *p = 0 and char *ch = 0. p contains address 0x00000000 and ch contains the address 0x00000000
2.Why is this giving me the address difference that the respective pointer has obtained while incrementing, or is this a undefined
behavior.
char *ch = 0; means that ch contains the address 0. Incrementing the address using ++ will increment the value by sizeof(char) viz 1. Similarly for integer. p contains the address 0. And using the ++ operator increments the value by sizeof(int) which seems to be 4 on your machine(note, this isn't always true, especially for 64 bit machine).
3.Why this output is 4 1 ? here
Because at first, p contained 0, then incremented by sizeof(type_of(p)) = sizeof(int) = 4 on your machine and ch incremented by sizeof(type_of(ch)) = sizeof(char) = 1.
First, your code is printing pointers as integers. While this is probably what you're trying to do, it is not defined behavior, as it is entirely unportable on platforms where the size of a pointer (in bytes) is not the same as the size of int. if you want to print pointer values, use %p instead.
To answer your questions. You are assigning values to both pointers: 0, which is synonymous with NULL.
Second. The reason you're getting 4 1 is due to the size of an int vs the size of a char on your platform. The char is going to be 1. On your platform, anint is 4 bytes wide. When incrementing a pointer the compiler will automatically move the address it references by the byte-count of the underlying type it represents.
#include<stdio.h>
int main()
{
int *p=0; // int is 4 bytes on your platform
char *ch=0; // char is 1 byte
p++; // increments the address in p by 4
ch++; // increments the address in ch by 1
printf ("%d and %d\n",p,ch);
return 0;
}
EDIT: you're going to get the similar results, but with a supported print statement, do this instead:
#include<stdio.h>
int main()
{
int *p=0;
char *ch=0;
p++;
ch++;
printf ("%p and %p\n",p,ch);
return 0;
}
Output (on my Mac) is:
0x4 and 0x1
As per my knowledge, I have added the answers to your questions inline:
#include<stdio.h>
int main()
{
int x=0,*p=0;
char c = 'A', *ch=0;
x++;
// You have initialized this to 0, so incrementing adds 4 (int pointer)
// Remember, the address '4' means nothing here
p++;
// You have initialized this to 0, so incrementing adds 1 (char pointer)
// Remember, the address '1' means nothing here
ch++;
// You are now printing the values of the pointers itself
// This does not make any sense. If you are using pointers, you would want to know what is being referenced
printf ("%d , %d and %d\n",x,p,ch);
// This will FAIL
// Because, you are now trying to print the data pointed by the pointers
// Note the use of '*'. This is called de-referencing
printf ("%d , %d and %d\n", x, *p, *ch);
// Let p point to x, de-referencing will now work
p = &x;
printf ("%d , %d\n", x, *p); // 1, 1
// Let ch point to c, de-referencing will now work
ch = &c;
printf ("%c , %c\n", c, *ch); // 'A', 'A'
return 0;
}
Hope this helps.

Resources