strange output issue in c - c

1) #include <stdio.h>
int main()
{
int a[5] = {1,2,3,4,5};
int *ptr = (int*)(&a+1);
printf("%d %d", *(a+1), *(ptr-1));
return 0;
}
the output is 2 5. &a means the address of a[0] so &a+1 should be the address of a[1]. So ptr should hold the address of a[1]. *(a+1) will be 2 but *(ptr-1) should also be 2. I can't understand how is it printing 5.

This expression is the important thing: &a+1. That is actually (&a)+1 which is equal to (&a)[1] which will be a pointer to one element past the end of the array.
If we look at it more "graphically" it looks like this, with relevant pointers added:
+------+------+------+------+------+
| a[0] | a[1] | a[2] | a[3] | a[4] |
+------+------+------+------+------+
^ ^ ^
| | |
| &a[1] (equal to *(a + 1)) |
| |
&a[0] (equal to a) |
| |
&a &a+1
First of all, the type of &a is int (*)[5], so your cast to int * will break strict aliasing (which leads to undefined behavior).
Second of all, since ptr is pointing, effectively, to what would be a[5] then ptr - 1 will point to a[4].

&a is not the address of a[0] but the address of a. The values may be the same but the types are different. That is important when it comes to pointer arithmetic.
In the expression &a + 1, you first have &a which has type int (*)[5], i.e. a pointer to an array of size 5. When you add 1 to that it actually adds sizeof(a) bytes to the pointer value. So &a + 1 actually points to one byte past the end of the array. You then cast this expression from int (*)[5] to int * and assign it to ptr.
When you then evaluate *(ptr - 1), the - operator subtracts 1 * sizeof(int) from the byte value of ptr so it now points to the last element of the array, i.e. 5, and that is what is printed.

&a gives the address of the array as an array pointer, int (*)[5]. It is a pointer type that points at the array as whole, so if you do pointer arithmetic with it, +1 will mean +sizeof(int[5]) which is not what you intended.
Correct code:
int *ptr = a+1;
Notably, the cast (int*) was hiding this bug. Don't use casts to silence compiler errors you don't understand!

Firstly, you said: &a means the address of a[0] so &a+1 should be the address of a[1] ? No you are wrong. &a means address of a not a[0]. And &a+1 means it increments by whole array size not just one elements size and a+1 means address of a[1].
Here
int a[5] = {1,2,3,4,5};
lets assume base address of a is 0x100
--------------------------------------
| 1 | 2 | 3 | 4 | 5 |
--------------------------------------
0x100 0x104 0x108 0x112 0x116 ..
LSB
|
a
When you are doing
int *ptr = (int*)(&a+1);
Where ptr points ? first (&a+1) performed and it got increments by whole array size i.e
(&a+1) == (0x100 + 1*20) /* &a+1 here it increments by array size */
== 0x120
So now ptr points to
--------------------------------------
| 1 | 2 | 3 | 4 | 5 |
--------------------------------------
0x100 0x104 0x108 0x112 0x116 0x120
a |
ptr points here
Now when you print like
printf("%d %d", *(a+1), *(ptr-1));
Here
*(a+1) == *(0x100 + 1*4) /* multiplied by 4 bcz of elements is of int type*/
== *(0x104) /* value at 0x104 location */
== 2 (it prints 2)
And
*(ptr-1) == *(0x120 - 1*4)
== *(0x116) /* prints value at 0x116 memory location */
== 5
Note :- Here
int *ptr = (int*)(&a+1);
type of &a is of int(*)[5] i.e pointer to an array of 5 elements but you are casting as of int* type, as pointed by #someprogrammerdude it breaks the strict aliasing and lead to undefined behavior.
Correct one is
int *ptr = a+1;

Related

How does incrementing memory address affects pointer

I am seeking for an explanation regarding how incrementing an address affects a pointer.
I learned about how C pointers work and how incrementing a pointer is done by considering the pointer type. still I don't understand the following case
int main()
{
int a[] = {1,2,3,4,5};
int *p = (int*)(&a+1);
printf("%d\n%d\n", *(a+1), *(p-1));
return 0;
}
I expected this line
int *p = (int*)(&a+1);
to make p point to the address that follows array a, therefore I expected the output:
2
as it is simply a[1]
But the output was unknown_number - as I don't know which int is 4 bytes behind (&a+1)
And the actual result is:
2
5
Why does it seems that p points directly to the memory sitting after a?
What is the source for my confusion?
So in this example &a is of type int(*)[5]. When you add 1 to it it actually adds sizeof(int[5]) - because that is how pointer arithmetic works, adding an offset adds the size of the type being pointed to times the offset. That is how you get p to be one past last element of a, after which you cast it to int* so now you have a pointer pointing to an integer at an address one past the last element of a. So effectively, subtracting 1 from it gives you the last element of a.
Two basic concepts:
Except when it is the operand of the sizeof or unary & operators, or is a string literal used to initialize a character array in a declaration, a 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.
Adding 1 to an expression of type "pointer to T" yields the address of the object of type T immediately following the current object. IOW, if p points to a 4-byte int, p+1 points to the int immediately following it. If p points to a 5-element array of int, then p+1 points to the next 5-element array of int immediately following it. This is how array indexing works - the subscript operation a[i] is defined as *(a + i). Given a starting address a (either a pointer expression or an array expression that decays to a pointer), find the address of the i’th object following that address and dereference the result.
So, if you have the declaration
int a[] = {1, 2, 3, 4, 5};
then the following are true:
the expression a has type "5-element array of int" (int [5]) - if the expression is not the operand of the sizeof or unary & operators, it "decays" to type "pointer to int" (int *) and its value is the address of the first element of the array (&a[0]).
the expression *(a + 1) is identical to a[1], and evaluates to the second object in the array (2).
the expression &a + 1 has type int (*)[5] and yields the starting address of the 5-element array of int after a. The type of this expression is converted to int * and assigned to p.
the expression p has type int * - subtracting 1 from this yields the address of the int object immediately preceding p, which happens to be the last element of a.
Graphically:
+–––+
a: | 1 |
+–––+
| 2 | <–– a + 1
+–––+
| 3 |
+–––+
| 4 |
+–––+
| 5 | <–– p - 1
+–––+
| ? | <–– p (&a + 1)
+–––+
You can manipulate the array a as a pointer to a int int *. But it is not the same for &a, which is a pointer to an array of 5 ints : &a + 1 will add the size of the 5 ints to the pointer.
Just remove the & before adding 1 to a, and it'll work as you expected:
#include <stdio.h>
int main()
{
int a[] = {1,2,3,4,5};
int *p = (int*)(a+1); // & removed
printf("%d %d\n", *(a+1), *(p-1));
return 0;
}

Difference between `*&p` vs `&*p`?

int a=10;
int *p=&a;
now looking at &*p we first look at *p which is 10 and then at &10
which is the address of 10 or the address of a
In the case of *&p we first look at the address of p and then at the value in this address which is 10
But I understand that both *&p vs &*p are the same, why?
Lets draw your variables:
+---+ +---+
| p | --> | a |
+---+ +---+
That is, p is pointing to a.
Now if you do &*p then you first dereference p to get a, then you get the address of a, which leaves you with a pointer to a.
If we take *&p then you get the address of p to get a pointer to p, then you dereference that pointer to get p. Which is a pointer to a.
So while the expressions do different things, the end result is the same: A pointer to a.
And a descent compiler would probably just do nothing at all, since the dereference operator * and address-of operator & together will always cancel each other out, no matter in which order they are.
Considering below example
int a=10;
int *p=&a;
this
*&p
means here both * and & gets nullified and it result in p which is nothing but &a.
And this
&*p
means first dereference p which gives a and then reference & i.e address of a which is nothing but p, same as the first case.
By the clockwise / spiral rule:
For *&p:
+-----+
| +-+ |
| ^ | |
* & p ; |
^ ^ | |
| +---+ |
+-------+
We first take the address of p, which is at this point the address of the address of a.
Then we dereference that, which gives the address of a.
For &*p:
+-----+
| +-+ |
| ^ | |
& * p ; |
^ ^ | |
| +---+ |
+-------+
We first dereference p, which gives us a.
We then take the address of that, which gives us the address of a, just like before.
In this context, & takes the address (i.e., informally "adds *" to the type of the expression). Meanwhile * dereferences a pointer (i.e., "removes a *" from the type of the expression). Therefore:
int *p = …;
p; // int *
*p; // int
&*p; // int *
&p; // int **
*&p; // int *
So, yes, in this context the result is the same: a pointer to int, because the & and the * cancel out. However, this is also why the combinations are pointless: the result is the same as p by itself.
*&p == *(&p). &p is an pointer to the pointer or int. *(&p) is a value to which pointer of pointer points, which is value of p. To continue, **&p will print '10'.
&*p == &(*p) where *p is the value at which the pointer points (value of a). Now & is an address of a, which is p again. And to go further, *&*p will print value of a (10).

Different Pointer Arithmetic Results when Taking Address of Array

Program:
#include<stdio.h>
int main(void) {
int x[4];
printf("%p\n", x);
printf("%p\n", x + 1);
printf("%p\n", &x);
printf("%p\n", &x + 1);
}
Output:
$ ./a.out
0xbff93510
0xbff93514
0xbff93510
0xbff93520
$
I expect that the following is the output of the above program. For example:
x // 0x100
x+1 // 0x104 Because x is an integer array
&x // 0x100 Address of array
&x+1 // 0x104
But the output of the last statement is different from whast I expected. &x is also the address of the array. So incrementing 1 on this
will print the address incremented by 4. But &x+1 gives the address incremented by 10. Why?
x -> Points to the first element of the array.
&x ->Points to the entire array.
Stumbled upon a descriptive explanation here: http://arjunsreedharan.org/post/69303442896/the-difference-between-arr-and-arr-how-to-find
SO link: Why is arr and &arr the same?
In case 4 you get 0x100 + sizeof x and sizeof x is 4 * sizeof int = 4 * 4 = 16 = 0x10.
(On your system, sizeof int is 4).
An easy thumbrule to evaluate this is:
Any pointer on increment points to the next memory location of its base type.
The base type of &x here is int (*p)[4] which is a pointer to array of 4 integers.
So the next pointer of this type will point to 16 bytes away (assuming int to be 4 bytes) from the original array.
Even though x and &x evaluate to the same pointer value, they are different types. Type of x after it decays to a pointer is int* whereas type of &x is int (*)[4].
sizeof(x) is sizeof(int)*4.
Hence the numerical difference between &x and &x + 1 is sizeof(int)*4.
It can be better visualized using a 2D array. Let's say you have:
int array[2][4];
The memory layout for array is:
array
|
+---+---+---+---+---+---+---+---+
| | | | | | | | |
+---+---+---+---+---+---+---+---+
array[0] array[1]
| |
+---+---+---+---+---+---+---+---+
| | | | | | | | |
+---+---+---+---+---+---+---+---+
If you use a pointer to such an array,
int (*ptr)[4] = array;
and look at the memory through the pointer, it looks like:
ptr ptr+1
| |
+---+---+---+---+---+---+---+---+
| | | | | | | | |
+---+---+---+---+---+---+---+---+
As you can see, the difference between ptr and ptr+1 is sizeof(int)*4. That analogy applies to the difference between &x and &x + 1 in your code.
Believe it or not, the behaviour of your program is undefined!
&x + 1 is actually pointing to just beyond the array, as #i486's answer cleverly points out. You don't own that memory. Even attempting to assign a pointer to it is undefined behaviour, let alone attempting to dereference it.

Why won't *num show the zeroth element value?

In this code:
#include<stdio.h>
int main()
{
int num[2] = {20, 30};
printf("%d", num);
printf("%d", &num[0]);
return 0;
}
As far as I know, both the printf statement will print the address of the first element in num because in the first statement, num is a pointer to an int.
But if num is a pointer, then it should also have any address but on printing its address (with printf("%d", &num)), it's showing the address of the first element.
In a 2-D array the whole thing becomes confusing too:
#include<stdio.h>
int main(void)
{
int num[ ] [2]={20,30,40,50};
printf("%d",*num);
return 0;
}
This program is printing the address of zeroth element that is the address of num[0][0]. But why does it do this? Why isn't it printing the value stored in it, since they all have same address(num,num[0] and num[0][0])?
First things first; array variables are not pointers; they do not store an address to anything.
For a declaration such as
T a[N];
memory will be laid out as
+---+
a[0]: | |
+---+
a[1]: | |
+---+
...
+---+
a[N-1]: | |
+---+
For a 2D MxN array, it will look like
+---+
a[0][0]: | |
+---+
a[0][1]: | |
+---+
...
+---+
a[0][N-1]: | |
+---+
a[1][0]: | |
+---+
a[1][1]: | |
+---+
...
+---+
a[M-1][N-1]: | |
+---+
The pattern should be obvious for 3D and higher arrays.
As you can see, no storage is set aside for a separate variable a that contains the address of the first element; instead, there is a rule in the C language that 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, except when the array expression is one of the following:
an operand of the sizeof operator
an operand of the unary & operator
an operand of the _Alignof operator (C99 and later)
a string literal used to initialize an array in a declaration
So given the declaration
T a[N];
all of the following are true:
Expression Type Decays to Value
---------- ---- --------- -----
a T [N] T * address of first element, &a[0]
*a T n/a value stored in first element
&a T (*)[N] n/a address of the array, which is
the same as the address of the
first element of the array
a[i] T n/a value stored in the i'th element
&a[i] T * n/a address of the i'th element
sizeof a size_t n/a total number of bytes used by the
array
sizeof *a size_t n/a total number of bytes used by the
first element of the array
sizeof &a size_t n/a total number of bytes used by a
pointer to the array
The expression a has type "N-element array of T"; it is not the operand of the unary & or sizeof operators, so it is converted to a pointer to the first element of the array, amd its value is the address of that element.
The expression &a has type "pointer to N-element array of T"; since a is an operand of the unary & operator, the conversion rule above isn't applied (which is why the expression has type T (*)[N] instead of T **). However, since the address of the array is the same as the address of the first element of the array, it yields the same value as the expression a.
The expression &a[0] has type "pointer to T", and explicitly points to the first element of the array. Again, this value will be the same as the previous two expressions.
For a 2D array
T a[M][N];
all of the following are true:
Expression Type Decays to Value
---------- ---- --------- -----
a T [M][N] T (*)[N] address of first subarray, a[0]
*a T [N] T * address pf first subarray, a[0]
&a T (*)[M][N] n/a address of the array, which is
the same as the address of the
first subarray, which is the same
as the address of the first element
of the first subarray.
a[i] T [N] T * address of first element of i'th
subarray
*a[i] T n/a value of first element of i'th subarray
&a[i] T (*)[N] n/a address of the i'th subarray
sizeof a size_t n/a total number of bytes used by the
array
sizeof *a size_t n/a total number of bytes used by the
first subarray
sizeof &a size_t n/a total number of bytes used by a
pointer to the array
Final note: to print out pointer values, use the %p conversion specifier and cast the argument to (void *) (this is the pretty much the only time it's considered proper to explicitly cast a pointer to void *):
printf( " &a yields %p\n", (void *) &a );
printf( " a yields %p\n", (void *) a );
printf( "&a[0] yields %p\n", (void *) &a[0] );
Edit
To answer a question in the comments:
num,num[] and num[][] are all different thing. There types are different.Here num decays and became pointer to a pointer and num[] decays and became pointer to int and num[][] is a int. Right?
Not quite.
Assuming a declaration like
int arr[10][10];
then the expression arr will decay to type int (*)[10] (pointer to 10-element array of int), not int **; refer to the table above again. Otherwise you're right; arr[i] will decay to type int *, and arr[i][j] will have type int.
An expression of type "N-element array of T" decays to type "pointer to T"; if T is an array type, then the result is "pointer to array", not "pointer to pointer".
In the second example, num is a 2 dimensional array, or say an array of array. It's true that *num is its first element, but this first element is an array itself.
To get num[0][0], you need **num.
printf("%d\n", **num);
Look how an array looks like:
int num[ ] [2]={20,30,40,50};
is better written as
int num[][2]={{20,30},{40,50}};
It is an array with 2 elements. Those 2 elements are, again, arrays with 2 ints.
In memory, they look like
20 30 40 50
but the difference is that num refers to the whole array, num[0] to the first "part- array" and num[0][0] to the first element of the first array.
They have the same address (because they start at the same place), but they have a different type.
That is, the address is not the only important thing with a pointer, the type is important as well.
Arrays are not pointers actually, though they tend to act in a bit similar way, but not always.
Say you have this array and a pointer:
int a[] = {1, 2, 3};
int i = 19;
int *ptr = &i;
Now here a is equal to &a, but the same is not true, for pointers (ptr is not equal to &ptr).
Now coming to the question:
Consider a single dimensional array:
int arr[] = {11, 19, 5, 9};
Here, this array elements are stored in contiguous memory locations. Say, with starting address 0:
---------------------
| 11 | 19 | 5 | 9 |
---------------------
0 4 8 12 16
Now when you write name of the array, arr (for this example), you will get the starting address of the 1st element. Though if you write &arr, then you get the starting address of the whole block(this includes all the elements of the array). Now when you write *arr, you actually get the value inside the 1st element of this array.
Now consider this 2-dimensional array arr[][4] = {{11, 19, 5, 9}, {5, 9, 11, 19}}:
0 4 8 12 16 -> These are memory addresses
---------------------
| 11 | 19 | 5 | 9 | ----> These values represent the values inside each index
---------------------
| 5 | 9 | 11 | 19 |
---------------------
16 20 24 28 32
Here, when you write the name of the array, as arr, what you get is the address of the 1st element of this array, which in this case will be address of this 0th index:
0 16 32
----------------------------------------------
| 0<sup>th</sup> index | 1<sup>st</sup> index |
----------------------------------------------
Now when you do &arr, here what you get is the base address for whole of the block, i.e. base address of this:
0 4 8 12 16
---------------------
| 11 | 19 | 5 | 9 |
---------------------
| 5 | 9 | 11 | 19 |
---------------------
16 20 24 28 32
Now, if you do *arr, in 1-dimensional array it gives you the value inside the 1st element, though in 2-dimensional array, the value inside each index is actually one 1-dimensional array, hence you will get the address of this array:
0 4 8 12 16
---------------------
| 11 | 19 | 5 | 9 |
---------------------
Now if you do **arr, that is when you will actually get the value inside the 1st element, which is 11.
I hope it clears some doubts :-)
EDIT 1:
As brought to my attendtion, by fellow user, it seems there is a bit of a confusion somewhere, though I have explained in detail what is meant by what thingy. But just to justify, for this statement:
Now here __a is equal to &a__, but the same is not true, for pointers (__ptr is not equal to &ptr__).
The types of both a and &a will be different, as already stated, in the answer. If one performs pointer arithmetics, one will able to know that. Try performing a + 1 and &a + 1, how they both react to pointer arithmetics will surely give a good idea.
Considering a 1-dimensional array:
int arr[] = {11, 19, 5, 9};
---------------------
| 11 | 19 | 5 | 9 |
---------------------
0 4 8 12 16
We cannot do a++, though for a pointer:
int i = 4;
int *ptr = &i;
we can perform ptr++, this will make ptr point to the next memory location.
I think it result means that the array not really a pointer, but it is converted to a pointer in some contexts that is expected a pointer, like pass to a function that expect a pointer argument.
see this code:
void test(int* num) {
printf("test\n");
printf("%p\n",num);
printf("%p\n",&num);
printf("%p\n",&num[0]);
}
int main(){
int num[2]={20,30};
test(num);
printf("main\n");
printf("%p\n",num);
printf("%p\n",&num);
printf("%p\n",&num[0]);
//other();
return 0;
}
The output is:
test
0x7fff7a422300
0x7fff7a4222e8 //LOOK THIS! Is diferent from main!
0x7fff7a422300
main
0x7fff7a422300
0x7fff7a422300
0x7fff7a422300

What is the the output of the following C programme?

I don't know what the compilar is doing with ++*p;
Can anyone explain me pictorically what is going on inside the memory in this code?
int main()
{
int arr[]={1,2,3,4};
int *p;
p=arr;
++*p;
printf("%d",*p);
}
The answer should be 2
The reason is ++*p is is actually incrementing the first member in the array by 1.
You are incrementing the first element in that array by creating another int pointer p that points to the element. The line
++*p
increments the value of the object pointed to by p - in this case it is the first element in the array.
Making up the actual memory addresses and using "ma" for memory address
at memory address starting at 1000 we have 4 continuous 4-byte (sizeof(int) = 4) slots.
each slot contains the integer value given in the array initializer:
arr
ma1000 ... ma1015
_____________________
| 1| 2| 3| 4|
_____________________
arr gives the starting address of the 4 int slots and how many there are.
p holds the address of an integer and refers to one 8-byte slot in memory (assuming we are on a 64-bit system where pointers are 8 bytes - 64 address bits/8bits-per-byte) at location 2000.
After the statement p = arr, p holds the address 1000
p *p or arr[0]
ma2000 .. ma2007 ma1000 .. ma1003
__________ ________
| 1000| | 1 |
__________ ________
*p gives the value at the memory address pointed to by p. p holds memory address 1000 and memory address 1000 contains 1, thus *p results in 1.
++*p says to increment the value of the int "pointed to" by p. p holds memory address 1000 which holds the value 1. The value at address 1000 then goes from 1 to 2
arr
ma1000 ... ma1015
_____________________
| 2| 2| 3| 4|
_____________________
printf then prints the int value at the address "pointed to" by p, which is 2.
p *p or arr[0]
ma2000 .. ma2007 ma1000 .. ma1003
___________ ___________
| 1000| | 2|
___________ ___________
Let's take this line :
++*p
This will first dereference the p pointer, so access arr[0], then increment it.
if you print arr[0] now, it will be 2.
Then you print *p that is the same as printing arr[0], it equals 2.
Try replacing the first element by 41, your code will print 42.
When you have a pointer int *p, then p means "the memory address p points to and *p means "the contents of the memory address where p points to". ++ means pre-increment, which means increase the value by 1. Since the associativity of unary operators such as * and ++(prefix operators) is right-to-left, and * is closer to p than ++ when traversed right-to-left, * operates before ++. Therefore ++*p means "increment the value pointed to by p", not "increment p then get the value". It is clearer to write ++(*p), but it means the same thing.
The thing to understand is the difference between "increment the pointer", which means point to another value (e.g. ++p) and "increment the value that the pointer points to" (e.g. ++*p).
You can work this out, but that is all the information you need to understand it.
This is a very basic concept in understanding of pointers.
p = arr ;
The above code will make the pointer " p " to point towards what the " arr " is pointing to. " arr " itself is pointing to the 1st element.
*arr = *(arr + 0) = arr[0] = 1
*(arr + 1) = arr[1] = 2
*(arr + 2) = arr[2] = 3
and so on...
So now when you do ++(*arr) that means ++(1) = 2
As p = arr, you can do the remaining replacement and math.

Resources