Pointer to pointer issue - c

I created a pointer to pointer and a int array, but when I try to access the array via my pointer to pointer, it skips some elements and moves by two elements at a time (eg: from 1 to 3).
Here is my code:
int main(void) {
int c=10;
int p[5]={2,3,5,6,8};
int *x;
int **y;
x=p;
y=&p;
printf("p value is %d and p points to %d",p,&p);
printf("\n x is %d \n",x[1]);
printf("\n y is %d \n",y[0]);
return 0;
}
When I print y[1] it will print 5 instead of 3 and y[2] is printed as 8. I can't think of the reason. Can any one help me on this? Pointer x is is working fine and moves along the correct elements as x[0]=2, x[1]=3, x[5]=5.
also can any one explain why i get same value for p and &p

Okay, this question has been answered and an answer has been accepted, but even the accepted answer does not explain the weird results the original poster was seeing: why do y[1] and y[2] print 5 and 8? Here is the explanation.
Original poster: What output do you get from the following statements?
printf ("Size of integer: %zu\n", sizeof (int));
printf ("Size of pointer: %zu\n", sizeof (int*));
I'm going to bet that the output is:
Size of integer: 4
Size of pointer: 8
In other words, I'm guessing that you're compiling on a 64-bit machine where the size of an integer is 4 bytes and the size of a pointer is 8 bytes. Based on that assumption, here's what is happening.
p is an array. With a few exceptions, when used in any expression, the array's name "decays" to a pointer to its first element. Any time you access the value of p, therefore, it will yield the address of its first element.
&p is one of those exceptions to the rule about arrays "decaying" to pointers. The address-of operator, when applied to an array's name, returns a pointer to the entire array--not a pointer to a pointer to the first element of the array.
What this means is that p and &p have the same value, but they are semantically very different. You will get the same value when you print:
printf("p value is %p and p points to %p", p, &p); // use %p and not %d for addresses
However, this does not mean that p and &p refer to the same thing. p is the address of first element of the array, i.e., &p[0]. On the other hand, &p is the address of the entire array of 5 integers.
So when you define x and y as follows:
int* x = p;
int** y = &p;
x is assigned a pointer to the first element of the array; y is assigned a pointer to the entire array. This is an important difference!
There is, moreover, a mismatch between how y is declared, and the value you're assigning to it. &p is of type int (*) [5]; a pointer to an array of 5 int. y is merely a pointer to a pointer to a single int. Your compiler should give you a warning about this mismatch. Mine does:
Warning: incompatible pointer types assigning to 'int**' from 'int (*) 5'
This mismatch explains the weird results while printing values of y[1] and y[2]. Let's look at what's going on with the values.
As you know, array subscripts are offsets from the beginning of the array:
x[0] == *(x + 0)
So x[0] yields the first element of the array, i.e., 2. Similarly
x[1] == *(x + 1)
But x is a pointer to int. So what is actually happining in the addition x + 1? Remember how pointer arithmetic works. Adding an integer to a pointer means you're actually adding that integer times the size of the element pointed to. In this case:
x + 1 == x + (1 * sizeof(int))
Since sizeof(int) is 4 on your system, the value of x[1] is the next integer in the array, which is 3.
So then, when you print y[0], how is this evaluated?
y[0] == *(y + 0)
Hence, the value that is at the address pointed to by y, i.e., at the address of p, is printed. This is the first element of p, hence you get the result 2.
What happens when you print y[1]?
y[1] == *(y + 1)
But what is y? It is a pointer to a pointer to an int. So when you add 1 to y, the way pointer arithmetic works is it again adds 1 * the size of the type of the element pointed to.
y + 1 == y + (1 * sizeof (int*))
The size of an int* is 8 bytes, not four! So every time you increment y by 1, you're incrementing it by 8 bytes, or the size of two integers. Hence, when you dereference that value, you are getting not the next integer in the array, but the integer that is two away.
To explain more clearly: Let us assume that the array begins at element 1000. Then, because each int takes four bytes, the following is the case:
Address Element
-----------------------
1000 2
1004 3
1008 5
1012 6
1016 8
p == &p == x == y == 1000
*x == *y == 2
When you add 1 to x, you are adding 1 * sizeof(int), i.e., you are actually adding 4. So you get 1004, and *(x + 1), or x[1], gives you 3.
But when you add 1 to y, you are adding 1 * sizeof(int*), i.e., you are actually adding 8. So you get 1008, and *(y + 1) gives you the element at address 1008, or 5.
This explains the output you are getting. This is NOT, however, a reasonable way to code. You should not expect that the size of a pointer is always going to be 8 bytes. You should not assign an int (*) [] to an int**. You should not dereference a pointer to a pointer to an int and expect to get an int result. And always heed compiler warnings.

This at least gives a clean compilation and uses %p to print pointers:
#include <stdio.h>
int main(void)
{
int p[5]={2,3,5,6,8};
int *x = p;
int **y = &x;
printf("p value is %p and the address of p is %p and p points to %d\n", (void *)p, (void *)&p, *p);
printf("x[1] is %d\n", x[1]);
printf("y[0] is the address %p\n", (void *)y[0]);
printf("y[0][0] is %d\n", y[0][0]);
return 0;
}
Sample output (Mac OS X 10.8.4, GCC 4.8.1, 64-bit compilation):
p value is 0x7fff5a1a54d0 and the address of p is 0x7fff5a1a54d0 and p points to 2
x[1] is 3
y[0] is the address 0x7fff5a1a54d0
y[0][0] is 2

Remember array name can easily decays into pointer to first element in most expressions.
p[] array in memory is like (addresses are assumption):
p
200 204 208 212 216
+----+----+----+----+---+
| 2 | 3 | 5 | 6 | 8 |
+----+----+----+----+---+
▲ ▲ ▲ ▲ ▲
| | | | |
p p+1 p+2 p+3 p+3
After x = p;, x also pointer to first element.
p
200 204 208 212 216
+----+----+----+----+---+
| 2 | 3 | 5 | 6 | 8 |
+----+----+----+----+---+
▲ ▲ ▲ ▲ ▲ ▲
| | | | | |
| p p+1 p+2 p+3 p+3
|
x
+----+
| 200|
+----+
In expression y = &p; , &p is pointer of array of type int(*)[5] and y is int**. (you must getting a warning (or error) compile with -Wall).
Read: Difference between &p and p
Because value-wise both p and &p are same so address value of y is also same as p.
p
200 204 208 212 216
+----+----+----+----+---+
| 2 | 3 | 5 | 6 | 8 |
+----+----+----+----+---+
▲ ▲ ▲ ▲ ▲ ▲
| | | | | |
| p p+1 p+2 p+3 p+3
|
x y
+----+ +----+
| 200| | 200|
+----+ +----+
int* int**
Your first printf:
printf("p value is %d and p points to %d",p,&p);
Should be written as:
printf("p value is %p and p points to %p", (void*)p, (void*)&p);
// ^ ^
Use %p instead of %d because you are printing addresses also typecast to void* is necessary because %p expects void*. As I said value-wise p and &p are same both addresses are same.
Second printf:
printf("\n x is %d \n", x[1]);
Outputs: 3 as x points to first element in array x[1] == *(x + 1) == 3 (in my figures x + 1 == 204).
Third printf:
printf("\n y is %d \n", y[0]);
Note y type is int** so y[0] == *(y + 0) = *y value stored at y type of *y is int*.
So again because y[0] is int* you should use %p instead of %d.
But the above printf statement prints value of first element that is: 2.
Similarly y[1] prints 3 and y[2] prints 5.
Edit
When I print y[1] it will print 5 instead of 3 and y[2] is printed as 8.
No, It outputs as I explained above Check #codepade where sizeof(int) == sizeof(int*) probably in your system sizeof(int*) = twice of sizeof(int) (64-bit compiler) so when you add one you address next to next location.
As #WhozCraig commented: Try y = &x; You may have better luck. And print anything you're passing that should be a "pointer" with %p.
Correct your code.

I think you code cann't compile successfully.
The type of &p is char (*p)[10], but the type of y is char **,
cannot convert from 'char (*)[10]' to 'char **'

Related

I am new to C and I have a question about pointers

The following lines of code work as you'd expect
#include <stdio.h>
int main(void)
{
int n;
int a[5];
int *p;
a[2] = 1024;
p = &n;
/*
* write your line of code here...
* Remember:
* - you are not allowed to use a
* - you are not allowed to modify p
* - only one statement
* - you are not allowed to code anything else than this line of code
*/
/* ...so that this prints 98\n */
printf("a[2] = %d\n", a[2]);
return (0);
}
This prints out a[2] = 1024
Now I was asked to modify this code so that a[2] = 98 gets printed instead. There were a ton of constraints. I couldn't use the variable a anywhere else in the code again and a couple other things. I found a solution online but I don't understand it at all.
#include <stdio.h>
int main(void)
{
int n;
int a[5];
int *p;
a[2] = 1024;
p = &n;
/*
* write your line of code here...
* Remember:
* - you are not allowed to use a
* - you are not allowed to modify p
* - only one statement
* - you are not allowed to code anything else than this line of code
*/
p[5] = 98;
/* ...so that this prints 98\n */
printf("a[2] = %d\n", a[2]);
return (0);
}
So, setting p[5] = 98; results in a[2] = 98 being printed, which is the intended result. I'm fairly new to C programming and pointers in general but I have absolutely no idea why this works the way it does.
This is all about the layout of the stack, the memory where the local variables in your method are stored. Variables are pushed onto the stack, so first the variable n is pushed to the stack, let us assume that it ends up at address 1000 (this is just a fictional address). Since it is an integer it takes up the space of an integer (4 bytes if integers are 32 bits). Then you push the array a to the stack. It will be located next to n.
Since n was placed at address 1000 and took up 4 bytes of memory, then a will be placed at address 1004 (1000 + 4). a is an array of 5 integers, each taking up 4 bytes. So a takes up the space from 1004 to 1024.
Your variable p is an integer pointer, and you set it to point to n. That means that p points to the address 1000 which is the address of n. You then write p[5] in C that is equivalent to the expression *(p + 5). Which basically means take value of the address p + 5. And since p is an integer pointer and each integer takes up 4 bytes, you are essentially asking for the value of address: 1000 + (5 * 4) = 1020
In the array a you stored the value 1024 at index 2, that corresponds to address: 1004 + 2 * 4 = 1012, so when you print the value of a[2] you are printing the value of address 1012. This means that the value you are setting to 98, is not a[2] but a[4].
The reason why I am mentioning this, is that in my case it did not print 98 but 1024. As people have already mentioned you are working with undefined behavior, and although it might work on some setups, it might not work on all.
I can't tell you the answer to your problem. But I can write a program which might, maybe, find the answer to your problem.
Try running this program:
#include <stdio.h>
int main2(int off)
{
int n;
int a[5];
int *p;
a[2] = 1024;
p = &n;
p[off] = 98;
return a[2];
}
int main()
{
int i;
for(i = -5; i <= 5; i++)
if(main2(i) == 98)
printf("the magic offset is %d\n", i);
}
On my computer, with one of my compilers, today, this program prints
the magic offset is 4
That tells me that (on my computer, with that compiler, today) the "solution" to your ridiculous problem would be
#include <stdio.h>
int main()
{
int n;
int a[5];
int *p;
a[2] = 1024;
p = &n;
p[4] = 98;
printf("a[2] = %d\n", a[2]);
}
I'm not even going to try to explain why this works, because the reasons are so obscure, unrepeatable, and meaningless. (See this question's other good answers for more details.) Basically the first program automates the search for a magic offset from p, more or less as you discovered.
And, in fact, under the first compiler I tried it, it didn't even work. Despite using the magic number 4 that the first program discovered, the second program printed a[2] = 1024. That's not too surprising: the relative positions of variables like a, p, and n are not specified by any standard. They're totally up to the compiler. The compiler is perfectly within its rights to arrange them one way in function main2 in my first program, and a completely different way in function main in my second program.
I tried my first program under a different compiler, and it printed
the magic offset is -3
and then crashed with a segmentation fault. But then, under that compiler, when I changed the relevant line in the second program to
p[-3] = 98;
it "worked", printing a[2] = 98 as required.
(And then I tried turning up the optimization level, and it stopped working.)
To be perfectly clear, the fact that my approach did not work under that first compiler, because it failed to arrange things in a consistent or predictable way, does not mean there's anything wrong with that compiler! Quite the contrary: the fault is entirely in the broken programs I wrote, and the broken assignment of yours that motivated them.
Here is an alternative exercise which will teach you something useful about arrays and pointers, without requiring that you "learn" false, unrepeatable facts about how variables are or aren't guaranteed to be arranged in stack frames.
#include <stdio.h>
int main(void)
{
int a[5];
int *p;
a[2] = 1024;
p = &a[4];
/*
* write your line of code here...
* Remember:
* - you are not allowed to use a
* - you are not allowed to modify p
* - only one statement
* - you are not allowed to code anything else than this line of code
*/
/* ...so that this prints 98\n */
printf("a[2] = %d\n", a[2]);
}
This problem has a similar solution — you can easily work it out — but the solution is unique and guaranteed to work, because it depends on well-defined properties of arrays and pointer arithmetic in C, not on accidental details of the stack layout.
It "works" by accident. It relies on n, p, and a being laid out in memory in a specific order (each box represents 4 bytes):
Address Item
------- --------
+---+
0x8000 n: | | p[0]
+---+
0x8004 p: | | p[1]
+---+
0x8008 | | p[2]
+---+
0x800c a: | | a[0] p[3]
+---+
0x8010 | | a[1] p[4]
+---+
0x8014 | | a[2] p[5]
+---+
0x8018 | | a[3] p[6]
+---+
0x801c | | a[4] p[7]
+---+
Some background:
A pointer is any expression whose value is the location of an object or function in a running program's execution environment - essentially, an address. A variable of pointer type stores an address value. However, pointers have associated type semantics - a pointer to int is a different type than a pointer to double, which is a different type than a pointer to struct foo, which is a different type than a pointer to an array of char, etc.
When you add 1 to a pointer value, the result is a pointer to the next object of the pointed-to type immediately following:
char *cp = &some_char;
short *sp = &some_short;
long *lp = &some_long;
+---+ +---+ +---+
some_char: | | <-- cp some_short: | | <-- sp some_long: | | <-- lp
+---+ | | | |
| | <-- cp + 1 | | | |
+---+ +---+ | |
| | <-- cp + 2 | | <-- sp + 1 | |
+---+ | | | |
| | <-- cp + 3 | | | |
+---+ +---+ +---+
| | <-- cp + 4 | | <-- sp + 2 | | <-- lp + 1
+---+ | | | |
... ... ...
This is exactly how array subscripting works - the array subscript operation a[i] is defined as *(a + i) - given a starting address a, offset i elements (not bytes!) from that address and deference the result. Arrays are not pointers; rather, array expressions "decay" to pointers to their first element under most circumstances. But this means you can use the [] subscript operator on pointer variables as well, so if you set p to point to n with
int *p = &n;
then you can apply the [] operator to p and treat it as though it was an array. So, if p == 0x8000 (the address of n), then p + 5 == 0x8014, which is the address of a[2]. Thus, *(p + 5) == p[5] == a[2] == *(a + 2).
But...
This behavior is undefined - it may work, it may not. It may result in garbled output, it may branch into some random subroutine, it may invoke Rogue. Neither the compiler nor the runtime environment are required to handle it in any particular way - any result is equally correct as far as the language is concerned.
We're pretending n is the first element of an array of int when it really isn't, so we're indexing out of bounds with p[1], p[2], etc. We're assuming objects are laid out in a specific order, but the compiler is under no obligation to lay variables out that way. The compiler may optimize things such that p is stored in a register, rather than on the stack.
This is a horrible way to teach pointers. It's unsafe, it's unportable, it's bad practice, it's confusing, it's an atypical use case, it doesn't explain why we use pointers. Whoever gave you this code shouldn't be teaching anyone how to program in C. If they write C for a living they are a menace.

Regarding the usage of functions with array subscript

Can some one explain me the logic with respect to the value of the variable b?
#include <stdio.h>
unsigned char buffer[4] = {1,2,3,4}; /* Declare the buffer */
unsigned char* u8GetHeader(void)
{
static int count = 0;
count++; /* incrementing the value of count for every invoke */
if(1 == count)
return &buffer[0];
else
return &buffer[1];
}
int main()
{
unsigned int a , b;
a = (u8GetHeader())[0];
b = (u8GetHeader())[1];
printf("The value of variable a = %d\n",a);
printf("The value of variable b = %d\n",b);
}
This program is a good candidate for working out on paper first and then stepping through the program to see if it matches your expectations.
Let us assume buffer is a global at address 0x1000.
The first call to u8GetHeader returns the address of buffer[0], which is just buffer or 0x1000. You then index it with 0, so you access the number at 0x1000 which is 1.
The second call returns the address of buffer[1], or 0x1001. You index it with 1, so you access the number at 0x1002, which is 3.
Why b gives you 3: Since count is static it will increment on each call. With b = (u8GetHeader())[1]; you call the function a second time so &buffer[1] is returned which is a pointer to {2,3,4} and its second value is 3.
Lets modify your program a little:
int main()
{
unsigned int a , b;
unsigned int *x, *y;
x = u8GetHeader();
y = u8GetHeader();
a = x[0];
b = y[1];
printf("The value of variable a = %d\n",a);
printf("The value of variable b = %d\n",b);
}
The first time the u8GetHeader function is called it returns a pointer to the first element of the array. This gets assigned to the x variable.
Each time after the first call, the u8GetHeader function will return a pointer to the second element. This gets assigned to the y variable.
Now if we "draw" the array and the pointers to the different elements in it it could look like this:
+---+---+---+---+
| 1 | 2 | 3 | 4 |
+---+---+---+---+
^ ^
| |
x y
It should be pretty clear that y is pointing to the value 2. That is y[0] == 2. From this it should also be quite clear that adding 1 to that index (i.e. y[1]) will then get the second element from y, which is the value 3. So y[1] == 3.
Perhaps it is also useful to know that for any array of pointer p and index i, the expression p[i] is exactly equal to *(p + i).
From this we get that y[1] then must be *(y + 1)., and if we add an arrow for y + 1 in the drawing we get:
+---+---+---+---+
| 1 | 2 | 3 | 4 |
+---+---+---+---+
^ ^ ^
| | |
x y y+1

Why output of *(arr + k) != *(&arr + k) although both refereed to same address

I am trying t print the content of array. Please find the code.
int main(){
int k = 2;
int arr[5] = {8,7,5,11,2};
printf("arr %p\n", arr);
printf("&arr %p\n", &arr);
printf("*(arr + k) %p\n", *(arr + k));
printf("*(&arr + k) %p\n", *(&arr+k));
}
I'm getting below output for above program where arr + k and &arr + k must be same.
arr 0x7ffe4e76ab60
&arr 0x7ffe4e76ab60
*(arr + k) 0x5
*(&arr + k) 0x7ffe4e76ab88
arr + k and &arr + k must be same
They are not the same.
In arr + k, advance k steps (each with size equal to sizeof *arr) and yield a value of the same type as decayed arr (int*).
In &arr + k, advance k steps (each with size equal to sizeof arr) and yield a value of the same type as &arr (int(*)[5]).
The step size is different in the 2 expressions. First it's the size of each element; second it's the size of the whole array.
The expressions arr and &arr evaluate to the same address, but they have different types:
arr - int *
&arr - int (*)[5];
Pointer arithmetic takes the size of the pointed-to type into account, so arr + 1 evaluates to the address of the next int, while &arr + 1 evaluates to the address of the next 5-element array of int.
+----+
arr[0] : | 8 | <--- arr, &arr
+----+
arr[1] : | 7 | <--- arr + 1
+----+
arr[2] : | 5 |
+----+
arr[3] : | 11 |
+----+
arr[4] : | 2 |
+----+
| ?? | <--- &arr + 1
+----+
| ?? |
+----+
| ?? |
+----+
| ?? |
+----+
| ?? |
+----+
arr is (by definition) the address of the first element (so it is a pointer to the base type of the array, in this case int), while &arr is the address of the array, so it is of type int[5]* (a pointer to an array of 5 ints). When you use (arr + 5) you are computing (pointer arithmetic) the value of a pointer to int and moving it 5 places up (5 times the size of an int). When you say (&arr + 5) you are computing the value of a pointer to int[5] and moving it 5 times the size of an array of 5 ints. This is five times what you move the previous pointer. This makes both addresses different, as the pointed types are of different sizes. The result values will be also different (the *(arr + 5) is the value pointed to at the fifth position of the array, while *(&arr + 5) is the value (an array of 5 ints) positioned 25 ints further in the memory, but as an array, when deferred gives the address of the first element, you'll get the value of the integer stored 25 places higher in memory.

%u format Specifier in C

I compiled this code and it gave the the value of '&x' 3 times. That is if &x = 2000 it printed 2036 three times. I want to know the reason for this behaviour assuming an integer requires 4 bytes of memory.
#include <stdio.h>
int main(void) {
// your code goes here
int x[4][3] = {0};
printf("%u %u %u", x+3, *(x+3), *(x+2)+3);
return 0;
}
What will be the output of this code
Anything can happen as the code provokes undefined behaviour by printing a pointer value using the conversion specifier for an unsigned.
To print pointer values use the conversion specifier p.
The address of an array and the address of its 1st element are the same. Pointers to them both however are of different type.
x as well as x + 3 are of type int (*)[3], that is pointing to an array of three ints. Assuming int to be of size 4, an array of three ints is of size 12.
Increasing x (a pointer to int (*)[3]) by three elements one ends up with an address 3 * 12 bytes beyond where x points to. This is called pointer arithmetic.
You're misusing a format specifier and invoking undefined behavior because of that. At that point, what happens is arbitrary and uninteresting.
If you want to print a pointer, use the %p specifier.
x is a pointer to an array of pointers. The array of pointers has 4 elements. Each of these four elements points to 3 integers.
Hence if x = 2000 then,
x[0] = 2000, x[1] = 2012, x[2] = 2024, x[3] = 2036.
Therefore,
x + 3 = 2036 (because x is an array pointer and it increases by 12 each time.)
*(x+3) = x[3] = 2036 again.
*(x+2)+3 = x[2] + 3 = 2024 + 3*4 = 2036 again.
Hence the output will be three same numbers.

Does nth index of n sized C array contain size of it?

I've written a C program for showing the values of an array using pointer. Here's the code :
#include <stdio.h>
int main()
{
int a[] = {1, 1, 1, 1, 1};
int *ptr = a;
for (int i = 0 ; i < 5; i++)
printf("%d ", *ptr++);
printf("%d", *ptr);
}
As you can see after terminating the loop, the pointer holds the memory address of a value out of the array. As it i.e. the last output is not initialized, it should be a garbage value. But, every time it is showing 5 which is the size of the array. Then, I thought the next memory address of allocated memory for array contains the size of array. But, this is not happening with double type array.
Output for int array : 1 1 1 1 1 5
Output for double array : 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000 0.000000
Will anyone explain the output?
This is just a value from memory in this address. You should never access memory which is not allocated by you (In this case you are accessing 6th element, but you have declared just 5). This may lead to segmentation fault is some cases.
C does not store any array metadata (including array length) anywhere, either at the beginning or the end of the array. In the case of the integer array, the most likely explanation for the output is that the memory used by the variable i immediately follows the last element of the array, like so:
+---+
a: | 1 | a[0]
+---+
| 1 | a[1]
+---+
| 1 | a[2]
+---+
| 1 | a[3]
+---+
| 1 | a[4]
+---+
i: | 5 | a[5]
+---+
However, you cannot rely on this behavior being consistent, as you saw with changing the array type to double.
Attempting to read the value contained in the element one past the end of the array results in undefined behavior. Chapter and (truncated) verse:
6.5.6 Additive operators
...
8 When an expression that has integer type is added to or subtracted from a pointer, the
result has the type of the pointer operand...If the result points one past the last element of the array object, it
shall not be used as the operand of a unary * operator that is evaluated.
For giggles, I compiled your code on my system at work, and I get the following output:
1 1 1 1 1 0
This really is just an artifact of how the compiler lays objects out in memory for this particular program.
What you do invokes Undefined Behavior.
It's simple a coincidence and probably just the value of i, print the address of i and check. But be careful, it will not always be that way. Just declare a new variable in the program and it might change.
In the case of double it doesn't work because the address after the array no longer matches the address of i. It's what I mean when I say Be careful.

Resources