tags:

views:

416

answers:

6

I know that pointers contain the addresses of variables, for example:

int c = 5;
int *p;  
p = &c;
printf("%d",*p); // Outputs 5.

But what if I want to send an address to a function:

void function (int *p)
{
  p++;
}
int c;
function (&c);

When function is called, the value of &c is assigned to int *p. I guess that the exact instruction is: *p = &c;, but I don't understand what this means.

+3  A: 

I prefer to write int* p = &c;, that is, a pointer to type int is being assigned the address of c.

Pointer notation can be confusing, as you've noticed, because these two are equivalent:

int *p = &c;

and

int *p;
p = &c;

Hope this helps!

EDIT: The confusion comes because * is used both as the dereference operator, and for declaring a pointer. So when p contains the address of c, *p dereferences the pointer and returns the value of c. But when you say int *p = &c;, the * is saying "p is a pointer to an int", but is not doing any dereferencing.

Skilldrick
+2  A: 

Are you sure p++; is what you mean to do in your function? That's incrementing the location pointed to by p, it's not incrementing the value at the current location. If you're wanting to increment the value (i.e. make c become 6), then what you want is (*p)++;.

Amber
No, it doesn't do "incrementing the location pointed to by p", it simply increments p.
anon
Sorry, poor phrasing on my part. Since `p` is a pointer, incrementing it invokes pointer arithmetic, which will move the memory address effectively pointed to by the pointer by one spot (changing the *location*, not the value *at* that location - that is what I meant by incrementing the location, as opposed to incrementing the value at the location).
Amber
+2  A: 

If you want the function to increment c when called with &c, then write this:

void function(int *p) { ++(*p); }

function(int *p) means that p is the function parameter. So whatever value the caller gives, that will be assigned to p (not to *p).

The type of p is int *. That is, p is a pointer-to-int.

If p is a pointer-to-int, then *p is the int it points to.

c is an int. Therefore &c is a pointer-to-int, and the int it points to is c. Therefore, if p is &c, then *p is c.

With my version of the function, this code:

int c = 5;
function(&c);

Does the same as this code:

int c = 5; // same as before
int *p;    // parameter of the function
p = &c;    // assign the caller's value to the parameter
++(*p);    // body of the function, increments *p, which is the same as c.

Which does the same as this code:

int c = 5;
++c;
Steve Jessop
thanks a lot man , this is exactly what i asked
hamza
+3  A: 

I can't really make out your question, but the function looks like bug to me and what you meant is, perhaps,

++(*p)

Otherwise it's a no-op.

Michael Krelin - hacker
Strictly, `p++` in that function invokes undefined behavior (because incrementing p creates a pointer to an invalid location). In practice, on all normal C compilers, it does nothing.
Steve Jessop
No, there's no undefined behavior, since the incremented p never makes it out of the function and is immediately discarded.
Michael Krelin - hacker
But even calculating such a pointer is undefined behavior, isn't it?
Alok
Shouldn't be. Dereferencing a pointer to an invalid location is what's illegal. We use null pointers all the time, and as long as we don't dereference them, they're perfectly fine.
Samir Talwar
@Samir Talwar: No, even creating an invalid pointer is undefined behavior. A null pointer is not invalid, though. @Alok and @Steve Jessop: Actually, this case is okay because you can create a pointer that points one past the end of an array (though you can't dereference it) and you can treat any pointer as pointing to a 1-element array.
jk
I am not so sure. See http://groups.google.com/group/comp.lang.c/msg/c2f41ecc656ca575 for example (and the whole thread there actually).
Alok
@j/k: I know about the one-past the array rule, but here ++p is definitely *not* one past an array, because p pointed to an individual int. In other words: int a, b[1]; int *p = a; ++p; is undefined behavior, but p = b; ++b; is not.
Alok
@Alok: From the C standard: "For the purposes of [additive] operators, a pointer to a nonarray object behaves the same as a pointer to the first element of an array of length one [...]" This is 6.3.6 Additive Operators in the C90 standard, and it's what the last part in my comment referred to.
jk
Of course even thinking about pointer to the invalid location is a crime, not to mention writing about it on stackoverflow. But as long as no one brings authorities attention to the incident we're more or less safe. But if you guys are serious about creating invalid pointer being undefined behavior you're in deep trouble.
Michael Krelin - hacker
+5  A: 
tommieb75
To be pedantic, it's only partially determined at compile time; depending on the OS and/or shared librariness [I know that's not a phrase] of the resulting object, it might be relocatable. But you still get a +1 for using the right level of detail for the questioner (which I certainly didn't...)
Mikeage
@Mikeage: Thanks :) Well, at compile time happens before linking right? ;) You're spot on there...maybe the word should have been 'at link-time' instead of compile-time...thanks for pointing it out! :)
tommieb75
actually, at load time; there are cases when it can be relocated at runtime
Mikeage
@Mikeage: Thanks...I was intending to make the explanation as simple as possible without getting to pedantic about it...actually - I never thought of that... duh! :)
tommieb75
+1  A: 

Others have answered your question. I will just add that a helpful way of reading pointer declarations is this. Let's say I have the following declaration:

int i;

This is really easy. Here, i is an int. Now, let's say I have this:

int *pi;

Here, you can either say that pi is a pointer to an int (which is correct). Another way to look at it would be that *pi is an int, i.e., when you have *pi in your code, that *pi will be of type int. Having understood that, I think it's easy to see that ++pi or pi++ doesn't increment the int, because pi is the wrong type. You want (*pi)++. The parentheses are needed because in C, the operator ++ has higher precedence than the unary operator *. Since you don't use any of the side effects of the increment, you can as well do: ++*p.

Of course, as with all the pointers, pi has to point to something useful for the above to make sense.

Alok