Pablo Fernandez
Pablo Fernandez

Reputation: 105220

simple pointers to pointers

I know why this works:

#include <stdio.h>

void cool_number(int **number) {
  int value = 42;
  int *p = &value;
  *number = p;
}

int main () {
  int *number;
  cool_number(&number);
  printf("number is %d\n", *number);
  return 0;
}

What I don't understand is why this doesn't (in my machine it prints 3700 or something like that).

#include <stdio.h>

void cool_number(int **number) {
  int value = 42;
  int *p = &value;
  int **x = &p;
  number = x;
}

int main () {
  int *number;
  cool_number(&number);
  printf("number is %d\n", *number);
  return 0;
}

Why aren't both equivalent?

Upvotes: 0

Views: 123

Answers (4)

syler
syler

Reputation: 126

#include <stdio.h>

void cool_number(int **number) {
  int value = 42; /* this "value" hold 42 value, 
                     and it lifetime is only in this function */
  int *p = &value; /* here we get the address of "value" in memory */
  *number = p;
}

int main () {
  int *number;
  cool_number(&number);  /* after this function the "value" in memory had been recyled
                            and may be used by other program */
  printf("number is %d\n", *number); /* so when we print value here it will be 
                                 a unpredictable value, somehow may be crash */
  return 0;
}

both the same principle

Upvotes: 0

aroth
aroth

Reputation: 54806

I assume they're not equivalent because number is passed by value, on the stack, as is standard for function parameters. Any changes that you make directly to number inside of cool_number() are modifying the local copy on the stack, and are not reflected in the value of number in main().

You get around this in the first example by dereferencing number, which tells the computer to modify some specific location in memory that you also happen to have a pointer to back in main(). You don't have this in the second example, so all that happens is that you make the local number pointer point to somewhere else, without actually updating any memory location being referred to back in main(). Thus nothing you do shows up once you get back to main().

And since value is local to the cool_number() function, setting a reference to it that will be accessed after cool_number() returns isn't guaranteed to work and certainly shouldn't be used in any code outside of a trivial/toy example. But in this specific instance it's not really related to why you're seeing different results between the two pieces of code.

Upvotes: 2

Jay
Jay

Reputation: 24895

As I understand, in both cases, your code is wrong.

  1. In the first case, you are returning an address to a variable allocated on stack, which will be deallocated as soon as the function returns.

  2. In the second case, the error of the first case exists, plus you are passing number by value, so an updation to number will not get reflected in the caller function.

In 'C', arguments are always passed by value. So, you cannot update the argument passed as it is. For Ex:

int func(int a)
{
  a = 5; // In this case the value 5 will not be reflected in the caller as what is updated is the local copy of a on the stack
}

int func(int *a)
{

  *a = 5; // This update will show in caller as you are directly updating the memory pointed to by a
   a = malloc(4); //This update will not show in caller as again you are updating the local copy of stack       
}

Upvotes: 1

Keith Nicholas
Keith Nicholas

Reputation: 44288

both are evil as they capture the address of a stack variable.

Second one doesn't do what you expect because you are assigning directly to the parameter number, which is only temporary, the first one changes something the parameter number pointers to, which is the same thing as number in main points to.

Upvotes: 3

Related Questions