2

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.

Skilldrick
  • 69,215
  • 34
  • 177
  • 229
hamza
  • 2,714
  • 3
  • 19
  • 14

6 Answers6

4

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
  • 69,215
  • 34
  • 177
  • 229
4

*p = &c; means:

Get the address of c in memory which is determined at compile-time link-time (Thanks Mikeage) e.g, 0x1234 as an example. The pointer to type int, i.e. *p is assigned to 0x1234, which does not sound right to me, I think you should be doing it this way, p = &c then *p would have the value pointed to by the address of c. And therefore *p would have the value of what c was assigned to (that is called dereferencing - by putting a * before the pointer variable then you can obtain the value).

In your function you are trying to increment the value pointed to by p.

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

// It would be called like this
int c = 5;
function(&c); // Now c would have 6!

The key point is you want to pass by reference which is what the parameter &c does. If you omit the passing by reference like this:

void function (int p)
{
  p++;
}
// And call it like this
int c = 5;
function(c); // c is still 5

Now c would still be 5, but within the function itself c is 6, but no copy is passed back out as it is incremented within the local stack for the function itself.

t0mm13b
  • 34,087
  • 8
  • 78
  • 110
  • 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 Dec 13 '09 at 13:35
  • @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! :) – t0mm13b Dec 13 '09 at 13:43
  • actually, at load time; there are cases when it can be relocated at runtime – Mikeage Dec 15 '09 at 09:29
  • @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! :) – t0mm13b Dec 15 '09 at 11:03
3

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
  • 273,490
  • 39
  • 460
  • 699
3

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
  • 138,757
  • 24
  • 193
  • 173
  • 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 Dec 13 '09 at 14:40
  • No, there's no undefined behavior, since the incremented p never makes it out of the function and is immediately discarded. – Michael Krelin - hacker Dec 13 '09 at 14:47
  • But even calculating such a pointer is undefined behavior, isn't it? – Alok Singhal Dec 13 '09 at 15:31
  • 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 Dec 13 '09 at 15:37
  • @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. – JaakkoK Dec 13 '09 at 15:46
  • 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 Singhal Dec 13 '09 at 15:52
  • @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 Singhal Dec 13 '09 at 15:53
  • @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. – JaakkoK Dec 13 '09 at 16:50
  • 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 Dec 13 '09 at 19:12
2

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
  • 507,862
  • 82
  • 626
  • 550
  • No, it doesn't do "incrementing the location pointed to by p", it simply increments p. –  Dec 13 '09 at 13:07
  • 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 Dec 13 '09 at 13:10
1

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 Singhal
  • 93,253
  • 21
  • 125
  • 158