C pointer always contains its own memory address? - c

Why does the pointer p always point to its own memory address as an integer in the following example. I can't see where it is initialized and would guess that it would be a garbage value. Can someone show me why it is not a garbage value. By the way I am compiling this in gcc with -std set to c99.
#include <stdio.h>
int main() {
int *p; int a = 4;
p = &a;
*p++;
printf("%d %u\n", *p, p);
}

Your problem (as the other answers point out) is with *p++;. What that says to do is dereference p then increment the address in p.
From what you are seeing, we can assume p comes directly after a in memory
_________________________________________
|something | a | p | something else |
-----------------------------------------
So what ends up happening is p points to a, then is incremented so it points to itself (or more specifically: p stores the address that p is at).

First you need to print a pointer value with %p, and your code has undefined behavior. You move the pointer one place after a and dereference it.
Your code doesn't illustrate the point you (it seems) wanted, the following will:
#include <stdio.h>
int main() {
int *p; int a = 4;
p = &a;
printf("%d %p %p\n", *p, p, &p);
}
It produces something like:
4 0x7fff5c17da44 0x7fff5c17da48
p points to a then *p is the value of a. The value of p is 0x7fff5c17da44 which is the adresse of a and the address of p (&p) is 0x7fff5c17da48.

Related

Why is the pointer giving me this value?

I was studying for a test with the following question with the given output :
#include <stdio.h>
int main()
{
int i = 10;
int *const p = &i;
foo(&p);
printf("%d\n", *p);
}
void foo(int **p)
{
int j = 11;
*p = &j;
printf("%d\n", **p);
}
Output : 11 11
I understand that the address of *p pointing to int i is passed to the function foo. Here, **p is a pointer pointing to *p, where *p points to int i.
In the function, **p pointer changes and points to int j, and the first printf is called and 11 is printed.
What I don't understand is the output from the 2nd printf function. Why is it printing 11, when it should be 10? I've checked and the value of int i and it did not change, so shouldn't dereferencing *p give 10 and not 11.
Can someone explain to me the logic behind what is happening and why is it happening?
First you asign p the address of i and you input the address of p to the function foo and inside the foo function the the value of p becomes what every the value in j (*p = &j). When the memory address changes in the foo function you are not changing it back.
NOTE: There the variable p is not passed by value, It is passed to the function by reference. So any change you do to the p variable inside the foo function will affect the p variable inside the main function because they have the same memory address
The line:
*p = &j;
makes the original variable
int *const p
point to the address of the local variable
int j
After foo is called, that local variable j has since been deallocated from the stack, but p is still pointing to that same stack location which still has that value of 11. So you are illegally accessing deallocated stack memory but it just happens to remain the value of 11. So it is printed a second time.

what does *p contain?

As per multiple sources, a pointer p points to a value when it is dereferenced. Thus, we may say that a pointer contains an address as it's value, and when the dereference operator (*) is used, the value at the address is returned.
A pointer may be assigned a value as follows:
int a = 90;
int *p = &a;
if we assign a pointer it's value as follows:
int *p;
*p = 60;
60 is alloted to p and causes undefined behavior upon dereferencing since 60 is not a valid address. (As per the answer to this question).
However, for the following code:
int a = 90;
int *p = &a;
printf ("p is %d \n",*p);
printf ("a is %d \n", a);
printf ("address is %p \n",p);
*p = 100;
printf ("p is %d \n",*p);
printf ("a is %d \n", a);
printf ("address is %p \n",p);
The following output is recieved :
p is 90
a is 90
address is 0028FED8
p is 100
a is 100
address is 0028FED8
ie, the expression *p = 100 changes the value at a, and not the value contained by p.
HOW ??????
*p = &a doesn't even compile. p is a pointer to int. It currently has an undefined value, therefore assigning anything to *p is undefined behaviour and would most likely crash. However, even if p did point to an int, you could only assign an int to *p, &a is a pointer to int, not an int, so this doesn't compile.
In your second example, *p = 60, the value of p is undefined, so you are trying to store 60 to an undefined location in memory. Instant crash. p isn't modified by this, so your explanation is wrong. p is not set to 60. You can't set p to an int. You can only set it to a pointer to int.
Correct:
p = &a;
*p = 60;
the code you wrote at the begining:
int *p;
int a = 90;
*p = &a;
is not valid, The asterisk (*) in line 1 indicate that it is a pointer, it is not the dereference operator as in line 3.
the following code:
int a = 90;
int *p = &a;
is equivalent to:
int a = 90;
int *p;
p = &a;
(p) is a pointer , and now is pointing at address of (a)
*p = 100;
so, you just assign a value to a, a = 100 .
and you are printing the same value from the same address.
You had asked:
ie, the expression *p = 100 changes the value at a, and not the value contained by p.
You can read the comment section for explanation of each line of C code and I'm not using exact address locations but using arbitrary ones for demonstration purposes:
int *p; // Stack variable pointer to integer type w/ p's address being 4 bytes # 0x00000000
int a = 90; // Stack integer variable `a` and initializing it to the value of 90 located # 0x00000040
*p = &a; // Dereferencing the pointer `p` to be equal to the address of `a` ... One would think
// that the address value of `a` 0x00000040 in hex would be stored into `a` which
// has the value of 64 in decimal, however this is not always the case and this should be
// undefined behavior, but can still compile and run depending on the compiler and architecture.
// It may run or crash or not even compile or build at all. Most compilers should throw an error.
*p = 100; // 'p' is located at 0x00000000 and contains the value 0x00000040 and by dereferencing it
// it will assign the value of 100 to the stack address location of 0x00000040. Thus this
// changes the value of `a` to 100
// These two statements are in a sense equivalent
*p = 100; a = 100;
// If one was to assign the address of `a` to `p` as such:
p = &a;
EDIT
// Therefor the statement `*p=100` will only work if the statement
// `p=&a` is defined and evaluated beforehand.
EDIT
Now as for the question based on the Title: "what does *p contain?" with the op's original code provided *p actually contains garbage or what ever was assigned to it upon declaration.
As per multiple sources, a pointer p points to a value when it is dereferenced.
Not quite. A pointer points to an object. Dereferecing a pointer produces that object. Using an object in a context where a value is needed produces the stored value.
int *p = &a;
The object that p now points to is a.
*p = 100;
Dereferencing p produces the pointed-to object, namely a. Since this is not a context where the stored value is needed, a's value isn't read, it remains the object a which is assigned the value 100.
Or, simply put, *p means a, therefore *p = 100 means a = 100.

C: Why do pointer and &pointer have different values?

If I run the following on OS X:
int main (void)
{
int* n; // initialise(declare) pointer
*n = 20; // the value in address pointed to by n is 20
printf("n: %i, n&: %i\n", n, &n);
return 0;
}
I get:
n: 1592302512, n&: 1592302480
Why the differing values?
Why do pointer and &pointer have different values?
The expression &n yields the address of n itself, while n evaluates to the value of the pointer, i.e. the address of the thing it points to.
But note that you have undefined behaviour First of all, because you are de-referencing an uninitialized pointer. You need to make n point somewhere you can write to.
For example,
int* n;
int i = 42;
n = &i;
// now you can de-reference n
*n = 20;
Second, you have the wrong printf specifier for &n. You need %p:
printf("n: %i, &n: %p\n", n, &n);
int* n declares a variable called n which is a pointer to an integer.
&n returns the address of the variable n, which would be a pointer to a pointer-to-integer.
Let's say we have the following code:
int a = 20; // declare an integer a whose value 20
int* n = &a; // declare a pointer n whose value is the address of a
int** p = &n; // declare a pointer p whose value is the address of n
In this case we would have the following:
variable name | value | address in memory
a | 20 | 1592302512
n | 1592302512 | 1592302480
p | 1592302480 | who knows?
In your code
int* n; //initialization is not done
*n = 20;
invokes undefined behavior. You're trying to de-reference (write into) uninitialized memory. You have to allocate memory to n before de-referencing.
Apart form that part,
n is of type int *
&n will be of type int **
So, they are different and supposed to have different values.
That said, you should use %p format specifier with printf() to print the pointers.
Just as an alternative, let me spell this out a different way.
char *ptr;
char c='A';
ptr = &c;
In this code, here's what's happening and what values are found when we qualify ptr in different ways.
ptr itself contains the address in memory where the char c variable is located.
*ptr dereferences the pointer, returning the actual value of the variable c. In this case, a capital A.
&ptr will give you the address of the memory location that ptr represents. In other words, if you needed to know where the pointer itself was located rather than what the address is of the thing that it points to, this is how you get it.

What is wrong with the pointer usage in this simple program?

I'm using VS 2010 Express, and I'm on Win Vista.
Here is the code:
#include <stdio.h>
int somefunc(char *p);
int main()
{
char *p = 0;
int x;
x = somefunc (p);
printf("%c", *p);
getch();
return 0;
}
int somefunc(char *p)
{
char y = '4';
p = &y;
return 2;
}
After I return to main(), I see the following in the autos window for p:
p 0x00000000 <Bad Ptr>
Anyone know why? It's as if the pointer is being treated as an automatic variable.
Btw, the x was just to create a similar condition to the same problem I was having in a larger program, but I don't think people want to sift through all of that code just to get to the meat of the problem, which is displayed here.
p in main() is a null pointer. It is passed by value to somefunc(), but that means that the value in the variable p in the function is a copy of the value in p in the main program, not a pointer to p itself. You change what the copy of p in the function points at; fortunately, it doesn't change what's in the main program.
Then you try to print what's at the position pointed to by the null pointer; this is undefined behaviour and programs typically crash.
If you had managed to change p in the main program, it would be pointing to an automatic local variable in somefunc() that would be out of scope — which is more undefined behaviour.
This would work:
#include <stdio.h>
int somefunc(char **p);
int main(void)
{
char *p = 0;
int x = somefunc(&p);
printf("%c\n", *p);
return 0;
}
int somefunc(char **p)
{
static char y = '4';
*p = &y;
return 2;
}
There are many other, possibly better, ways to make this work too.
I'm still confused on what *p = &y; means. If p in somefunc is a pointer to the pointer p, let's say p2 is a pointer to p1, then *p2 = p1, so *p2 is p1, which stores &y? Is that the correct way of thinking about this?
Basically, yes. First, let's rewrite the code to disambiguate the use of p:
int main(void)
{
char *p1 = 0;
int x = somefunc(&p1);
printf("%c\n", *p1);
return 0;
}
int somefunc(char **ppc)
{
static char y = '4';
*ppc = &y;
return 2;
}
The variable ppc is a pointer to pointer to char (hence the name ppc — not a name I'd normally use except for pedagogical purposes). I'll also rename p in main() to pq1, and introduce char *p2; in somefunc() which is a pointer to char.
Revising your comment in terms of these variables:
I'm still confused on what *ppc = &y; means. If ppc in somefunc() is a pointer to the pointer p1 in main(), then let's say ppc is a pointer to p1, then *ppc = p1, so *ppc is p1, which stores &y? Is that the correct way of thinking about this?
And that strongly shows that you're thinking is correct. One of the design guidelines for the C type nomemclature was that if you write:
SomeType *stp;
then *stp represents a value of type SomeType — declaration mimics use.
Now, with ppc, the declaration is char **ppc; and the declaration mimics use rule means that **ppc is a value of type char. Consequently, it means that *ppc is a value of type char *. It means that when you write to *ppc, you are modifying the space that ppc points at, and it points at the address of char *p1; in main() in the sample code.
You are modifying p in somefunc but this won't modify p in main. You probably need to pass a pointer to p if you want to modify its value.
Complementing Jonathan's answer, for your question
What is the difference between char **p and char p for the function parameter? Why can I pass and modify an array without having to return it, but I have to with a pointer? They are both addresses.
In C, there's no pass by reference, there's only pass by value i.e. any argument passed to a function is copied to its parameters, but can't be made to refer to the original. This is the reason functions like swap is implemented using pointers. Example
void swap(int *x, int *y)
{
int t = *x;
*x = *y;
*y = t;
}
int a = 0, b = 1;
swap(&a, &b);
Here &a is a pointer whose value is copied onto x, thus it is pass by value (sometimes, incorrectly, called pass by reference). So I should be able to do the same when modifying pointers too, right?
Nope. Since a pointer is already pointing to something, making it point another thing needs another level of indirection. An analogy would be: you know somewhere a direction sign is pointing towards your home, by just knowing where it's pointing to (home), would you be able to change the direction it's pointing? No, you'd have to know where the sign is to go there and make it point in another direction.
Likewise, say if a variable lives at level 0 then to edit it, we go to a level further i.e. level 1 to modify it (from outside). This concept can be applied recursively; so to edit a variable at level 1, we've to go to level 2 to modify them from outside and so on. Pictorially
type: int* int int*
variable name: ptr a pptr
-------- ------- --------
value: | 1000 | --> | 1 | <-- | 1000 |
-------- ------- --------
address: 2000 1000 2400
Notice that pptr can't change where ptr is pointing to since pptr too is pointing at what ptr is pointing at a. However
int** int* int
pptr ptr a
-------- -------- -------
| 2000 | --> | 1000 | --> | 1 |
-------- -------- -------
2400 2000 1000
now pptr (int**) is in a position to modify where ptr (int*) is pointing to. If you'd to modify pptr then you to go another level higher ppptr (int***) and so on.

Behavior of call by reference

In my program, I am a passing a pointer to a function. In that function, I am making the passed pointer to point to a location what another pointer points. When returned from function it no longer points to its new location, instead it points to its original location. As I am passing by call by reference, it should point to its new location. Why is this happening?
// a program to show behavior of call by reference
#include <stdio.h>
#include <stdlib.h>
void ptrAllocation(int *p)
{
int k = 10 ;
int *t = &k;
p = t ;
printf("\np now points : %d",*p);
}
int main()
{
int i = 5 ;
int *a = &i;
ptrAllocation(a);
printf("\na now points : %d",*a);
}
Output:
p now points : 10
a now points : 5
I know the problem can be solved if I make a function like:
void ptrAllocation(int **p)
{
int k = 10 ;
int *t = &k;
*p = t ;
printf("\np now points : %d",**p);
}
But I am not getting the clear picture of what is happening exactly in the program from the point of view of pointers, location, stack?
MY PROBLEM:
Is that the pointer k points to whatever pointer t points in the function ptrAllocation, but as the function returns, there no longer exists pointer t, hence pointer p points to its original location.
Is it not the case that when assigning a pointer to a pointer like in p = t, both pointers p and k point to the same location and not that p points to t and t points to the location.
Please describe how the stack and the pointers work in the program above.
You are passing by value, not by reference. What you pass by value is a pointer, but the pointer is still passed by value. You can change what it points at; you can't change the pointer in the calling function. If you wanted to do that, you'd have to pass a pointer to the pointer, as in your second code fragment.
Here's a derivative program based on your code, and its output from a 64-bit build on Mac OS X 10.8.3. I used 12 in the address printing to give uniform width pointer output on this machine; you can tune it to suit your machine.
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
static int q = 42;
static void ptrAllocation(int *p, int **z)
{
printf("p now points at: %2d (0x%.12" PRIXPTR ")\n", *p, (uintptr_t)p);
printf("z now points at: %2d (0x%.12" PRIXPTR ") (0x%.12" PRIXPTR ")\n", **z, (uintptr_t)*z, (uintptr_t)z);
int k = 10;
int *t = &k;
*z = &q;
p = t;
printf("After:\n");
printf("p now points at: %2d (0x%.12" PRIXPTR ")\n", *p, (uintptr_t)p);
printf("z now points at: %2d (0x%.12" PRIXPTR ") (0x%.12" PRIXPTR ")\n", **z, (uintptr_t)*z, (uintptr_t)z);
}
int main(void)
{
int i = 5;
int j = 7;
int *a = &i;
int *b = &j;
printf("Before:\n");
printf("a now points at: %2d (0x%.12" PRIXPTR ")\n", *a, (uintptr_t)a);
printf("b now points at: %2d (0x%.12" PRIXPTR ")\n", *b, (uintptr_t)b);
ptrAllocation(a, &b);
printf("a now points at: %2d (0x%.12" PRIXPTR ")\n", *a, (uintptr_t)a);
printf("b now points at: %2d (0x%.12" PRIXPTR ")\n", *b, (uintptr_t)b);
}
Sample output:
Before:
a now points at: 5 (0x7FFF59E1852C)
b now points at: 7 (0x7FFF59E18530)
p now points at: 5 (0x7FFF59E1852C)
z now points at: 7 (0x7FFF59E18530) (0x7FFF59E18538)
After:
p now points at: 10 (0x7FFF59E18534)
z now points at: 42 (0x000105DE8050) (0x7FFF59E18538)
a now points at: 5 (0x7FFF59E1852C)
b now points at: 42 (0x000105DE8050)
Studying the output should help you understand better what is going on. You can print more address values if you need to.
Please describe how the stack and pointers work in the program above.
I'll discuss the program I showed because the addresses are available for discussion.
The variable q is located at address 0x000105DEE8050. Inside main(), variable i is stored on the stack at memory location 0x7FFF59E1852C; the variable j is stored at memory location 0x7FFF59E18530. The variable a contains the address of i; b contains the address of j; the address of b itself is 0x7FFF59E18538; the address of a is not shown in the output.
When ptrAllocation() is called, the value of a is pushed onto the stack, and the address of b is also pushed onto the stack. It is an implementation detail which order the values are pushed.
Inside ptrAllocation(), the variable p contains a copy of the value in a in the main() function. The variable z contains the address of b in the main() function. The variable k is on the stack; the variable t contains the address of k.
The assignment *z = &q; assigns the address of q to the pointer b via the argument z; it changes what b points at by changing the value of b in the calling function — which is only possible because the address of b was passed.
The assignment p = t; changes the local variable p (which contains a copy of what is in the variable a in main()) so that it points to what t points at, which is k. Therefore, the 'After' print statements note that p points at the value 10. The value that **z points at is in q and is still 42; *z is the address of q.
On return, a in the main() code is unchanged because its address was not passed to ptrAllocation(), but b is changed because its address was passed to ptrAllocation() and ptrAllocation() modified the pointer.
As noted in the comments to the question, your second implementation of ptrAllocation() is flawed too:
void ptrAllocation(int **p)
{
int k = 10 ;
int *t = &k;
*p = t ;
printf("\np now points : %d",**p);
}
After calling this function, the pointer passed to it cannot reliably be dereferenced because *p points to a local variable which ceases to be valid once ptrAllocation() returns. You could fix this issue by making k into static int k = 10;, or by arranging for *p to point to some other int value that has a scope outside the function — a variable defined outside the function, or a dynamically allocated variable:
void ptrAllocation(int **p)
{
static int k = 10;
int *t = &k;
*p = t ;
printf("p now points : %d\n", **p);
}
Or:
void ptrAllocation(int **p)
{
*p = malloc(sizeof(*t));
if (*p != 0)
{
**p = 10;
printf("p now points : %d\n", **p);
}
}
Note, incidentally, how the code I've left has the newlines at the end of each printf() statement. Get into the habit of placing newlines at the end of lines of output. If you don't, you don't know when the output will appear (because it may be held up until the next time a newline is generated).
You are changing the pointer in function and not in the main code. Therefore only the copy will be changed. In the later case you change the location of pointer so the value at that address is changed. Take it like variables, when you change the copy, nothing happens to the original but when you change the location, the variable is changed. So you have to pass the address of pointer to change it.
The C language only implements call by value. Call by reference refers to passing (by value) a pointer p, and then using *p to manipulate what it points at (references).
If you want a function to change a pointer, you have to reference the pointer, such as by forming a pointer to pointer, and pass the reference to the function using call by value. The terms "reference" and "pointer" may be used nearly interchangeably in C — referencing is just what a pointer does.
In C++ call by reference is a language feature, but in C it's an idiom.

Resources