2

I have a function that takes a char **; it uses it internally for maintaining context between successive calls.

What is the difference between defining char **x and passing x to it, and defining char *x and passing &x?


For context: I tried to implement the example at strtok man page on my own before reading the source code. And I got segfaults. Then after attempts I looked at the source.

The problem was that I defined char **x and passed x as the **saveptr argument, but changing the definition to char *x and the passing to &x solved the problem.

What is the problem exactly?

Nour-eddin
  • 63
  • 7

3 Answers3

3

The first version, with char **x; and passing x, creates and uses an uninitialised pointer to pointer to char.
The second version, with char * x; and passing &x, creates an uninitialised pointer to char, but passes a value which is a valid address of a pointer to char, and is a defined value (i.e. like an initialised pointer to uninitialised pointer to char).

Basically with first version you ask to write at a "random" place in memory (almost sure way to get a segfault); with second, you ask to write into an existing pointer variable.

Yunnosch
  • 26,130
  • 9
  • 42
  • 54
1

When you define e.g.

char **x;

Then you simply define a pointer. It doesn't matter that it's a pointer to another pointer, the important part is that it's just a pointer. And as such, with the definition shown above, it's not initialized. It doesn't point anywhere special. Dereferencing it, like you most likely do in the function, leads to undefined behavior.

On the other hand, with a definition like

char *x;

and using &x to get a pointer to it, the pointer returned by &x points somewhere valid, to the variable x. Dereferencing &x will allow the function to access and modify x itself.

Using the address-of operator in this way is a way to emulate pass by reference, which C doesn't have.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • Thanks for the detailed answer! I never noticed that dereferencing an uninitialized pointer leads to undefined behavior (I thought it only causes segfault), and that passing by reference is simulated in C. – Nour-eddin Oct 25 '17 at 01:08
0

Because all function arguments are passed by value in C, if you define char **x and pass x, it won't be modified by the function. If you define char *x and pass &x, it can be modified (change its pointing address).

iBug
  • 35,554
  • 7
  • 89
  • 134
  • 1
    That's depend on where `x` is pointing to. If you write `char** x = &ptr_char`, and then pass that `x` to the function, you can change were `ptr_char` points to by `*x = new_address`. – ABu Oct 25 '17 at 00:17