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.
Related
why the op is 20 ?? not 10 ? I think the op should be 10 but I don't know what happened? can you please explain it step by step
void fun(int *ptr)
{
int q=10;
ptr=&q;
}
int main()
{
int r=20;
int *p=&r;
fun(p);
printf("%d",*p);
return 0;
}
Values of function arguments are copies of what is passed from caller. Modifying in callee will not affect caller's local variables.
Non-static local variables will vanish on exiting its scope. Therefore, you must not dereference pointers to them after that.
To obtain 10, your code should be:
#include <stdio.h>
void fun(int **ptr) /* pass a pointer to modify caller's local variable */
{static int q=10; /* add static to prevent it from vanishing */
*ptr=&q; /* dereference the pointer */
}
int main()
{int r=20;
int *p=&r;
fun(&p); /* pass the pointer */
printf("%d",*p);
return 0;
}
This is p and r (addresses are for instance based)
---------------- ---------------- ----------------
| r 20 | | p 1234 | | q 10 |
---------------- ---------------- ----------------
^ ^ ^
|_ Address of r |_ Address of p |_ Address of q
= 1234 = 9876 = 12121
To fun(),
void fun(int *ptr) {
int q = 10;
ptr = &q;
}
you provide p as ptr (ie 1234), then set ptr to the address of q
fun: ptr = 12121
then fun ends, and ptr dies with it, the memory didn't change for r
To change something you have to pass the address of that thing. Even if it is a pointer.
Giving the address of p to fun
fun( &p );
and changing fun() to accept a pointer to pointer
void fun(int **ptr) { // <== pointer to pointer
int q = 10;
*ptr = &q; // <== change r indirectly
}
here, ptr has the address of the pointer p, ie 9876
*ptr = &q; // changes the value of `r`
It´s basically because of two reasons:
p in main() and ptr in fun() are two different pointers, and
You pass p by value, not by reference.
At the function call:
fun(p);
you just pass p by value; Means it passes the address of r (what is actually the value of p) to ptr.
With ptr = &q; in fun() you just assign the address of q to ptr, but not to p.
Therefore, the output of dereferencing p at:
printf("%d",*p);
is of course 20, as p still point to r -> the value of p didn´t changed.
If you instead pass p by reference and declare ptr as pointer to pointer (**), plus qualify q with static qualifier (because function-local automatic variables will be destroyed after the function is executed once):
void fun(int **ptr) // ptr is declared as pointer to pointer to int.
{
static int q = 10; // q is static -> It won´t get destroyed after returning from `fun()`.
*ptr = &q; // dereferencing ptr to assign the address of q to p.
}
int main()
{
int r = 20;
int *p = &r;
fun(&p); // Notice the `&` to gain the address of `p`, not `r`.
printf("%d",*p);
return 0;
}
The output would be 10 as we actually assigned the address of q to p.
As a side note: It is considered as bad programming style to refer to static-qualified function-local variables from a caller. I just showed this to you for the educational purpose and to show the difference to your provided code.
Try to assign an object pointed to in the caller, here f.e. r, by a passed pointer inside of the called function, here ptr, with the actual value of the object in the called function, here q.
I am little confused and tried finding explanation but all "difference" questions asked are about type *name vs type* name which i know answer of.
I have code like this:
int a = 1;
printf("a = %d", a); // Prints 1
int *pt = a;
printf("pt = %d", pt); // Prints 1
*pt = 2; // Crash why? What am i pointing to here?
&pt = 2; // Not even compiling since
pt = 2; // Works
printf("pt = %d\n", pt); // Prints 2
printf("a = %d\n", a); // Prints 1
I know in order to change value of a i should have done int *pt = &a and then *pt = 2 and that is not my question.
My question is in this case, is using int *pt = a same as using int pt = a or is there any advantage of using it as pointer?
int a = 1;
...
int *pt = a;
Attempts to store the value 1 as the address held by pointer pt. Any dereference of pt is guaranteed to SegFault as address 1 is well down at the bottom of the system-reserved memory range -- which you have no ability to access, resulting in an access violation and SegFault.
What Is A Pointer?
A pointer is simply a normal variable that holds the address of something else as its value. In other words, a pointer points to the address where something else can be found. Where you normally think of a variable holding an immediate values, such as int a = 5;, a pointer would simply hold the address where 5 is stored in memory, e.g. int *b = &a;. It works the same way regardless what type of object the pointer points to. It is able to work that way because the type of the pointer controls the pointer arithmetic, e.g. with a char * pointer, pointer+1 point to the next byte, for an int * pointer (normal 4-byte integer), pointer+1 will point to the next int at an offset 4-bytes after pointer. (so a pointer, is just a pointer.... where arithmetic is automatically handled by the type)
So in your case:
int a = 1;
...
int *pt = &a;
Will assign the address where a is stored in memory to the pointer variable pt. You may then access the value at that address by dereferencing pt (e.g. *pt)
What you are doing is setting the address to which the pointer pt points to, to what a is currently holding (1 in your case). Since *a is most definitely not a valid and accessible address you will most likely get a segmentation fault when trying to dereference it. This is somewhat the same as if you are creating a null pointer by int *pt = 0 but instead of 0 you use whatever is in a.
Keep in mind that there is probably something funky going on with converting a signed int to an address which only makes the whole thing even worse.
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.
In the following code p is pointer to an int. It is quite clear that p points to the address of i. Through my research i know &p points to the address of pointer p. But i don't get why would you need separate address for that. And also when would you use &p.
int main() {
int i = 3, *p = &i;
printf("%p",&p);
printf("%p",p);
return 0;
}
If p is pointer to int then
int **q = &p;
When you want to use pointer to pointer, then use the address of a single pointer to assign it to pointer to pointer.
Just to make a point that pointer is also a data-type and it stored in the memory location and it holds a valid memory location as its value. The address in which this valid memory location is stored is given by &p
Your printf() also needs to be fixed. %p expects void *
printf("%p",(void *)p);
But i don't get why would you need separate address for that
You don't, but there exists the address of operator so you can take the address of a pointer, which is what
printf("%p\n", &p);
is printing.
And also when would you use &p
There are cases where this might be useful, consider for example that you need to pass a pointer to a function which could be reassigned into the function, you can do something like this
int allocateIntegerArray(int **pointerToPointer, size_t someSize)
{
if (pointerToPointer == NULL)
return 0;
*pointerToPointer = malloc(someSize * sizeof(int));
return (*pointerToPointer != NULL);
}
then you could use this funciton the following way
int *pointer;
if (allocateIntergerArray(&pointer, 10) == 0)
{
fprintf(stderr, "Error, cannot allocate integer array\n");
/* do some extra cleanup or recover from this error, or exit() */
exit(0);
}
The pointers themselves are also variables and as such they need to be sotred somewhere, so the address of a pointer tells you where is the pointer stored, it's value tells you where it is pointing to.
By knowing where it is stored you can do things like the one explained above.
A trivial example:
int nochange(int *c, int *val)
{
c = val; // Changes local pointer c to point to val
// Note that C passes copies of the arguments, not actual references.
}
int do_change(int **c, int *val)
{
*c = val; // Accesses the real pointer c at its real location and makes
// that one point to val
// Even though c is a pointer-to-pointer copy, its value is
// copied too, and the value is the address of the real c
}
int main()
{
int a = 1;
int b = 2;
int *c = &a; // A pointer is also a datatype that resides in memory
printf("%d\n", *c); // Will print 1
nochange(c, &b);
printf("%d\n", *c); // Will print 1
do_change(&c, &b);
printf("%d\n", *c); // Will print 2 because c now points to b
}
I have a similar answer with a bit more detail here about pointer vs pointer-to-pointer: pointer of a pointer in linked list append
There are some things that I still don't really understand with pointers when you pass them into functions.
If declare a function like
void help (const int *p)
can I modify the argument p within the function help?
Can I change what the pointer is pointing too?
Thanks for the clarification.
Yes, you can modify p. However, it won't change in the caller. C is a pass-by-value language. Check out the C FAQ, which has a question about exactly this situation.
In this case, since p is declared as a const int *, an attempt to modify p will be disallowed by the compiler.
However, if p were a plain old int *, you could modify the thing that p is pointing to, and the caller would notice. Say you wrote:
void foo(void) {
int n = 100;
help1(&n);
printf("n = %d", n);
n = 100;
help2(&n);
printf("n = %d", n);
}
void help1(int *p) {
*p = 50;
}
void help2(int *p) {
p = (int *)malloc(sizeof(int));
*p = 50;
free(p);
}
Then calling foo() would cause your program to print
n = 50
n = 100
In this program, help1 changes the thing that p points to, and the caller can see it. On the other hand, help2 makes p point to a different place in memory, and anything help2 does to modify that other location in memory is not visible to the caller.
The easiest way to understand const notation in C is to say the declaration out loud. Start with the name and go left:
const int *p; // 'p' is a pointer to an int that is const
This is by the way equal to:
int const *p;
This suggests that you can change the what p points at, but you can't change whatever it points at. So you have read-only access. However if you'd have something like this:
int * const p; // 'p' is a const pointer to an int
...then you could change the memory pointed to by p as much as you want, but you couldn't change p.