nsg
nsg

Reputation: 10580

What is the difference between a pointer to a pointer and the addressof a pointer in C?

What is the difference between initializing a variable x as char ** and initializing a variable x as char * and then using & to reference it? This question came up from the following inquiry:

I was looking at the man 3 strtol function. The function signature is:

long strtol(const char *restrict str, char **restrict endptr, int base);

So, to pass the endptr variable, I setup a variable:

char **endptr;

but when I passed it to the function it always returned NULL, even in cases where the str passed to strtol was something like abc.
I.E:

         char ** endptr;
         long exitval = strtol(args[1], endptr, 10); /* try to get the val */
         if (endptr != NULL) { /* it wasn't a valid base-10 number */

Yet when I changed how I initialized endptr to:

char *endptr;

and then passed the endptr as &endptr to the function, endptr was set correctly. I.E:

         char * endptr;
         long exitval = strtol(args[1], &endptr, 10); /* try to get the val */
         if (endptr != NULL) { /* it wasn't a valid base-10 number */

In both cases, I thought was I was passing was the a pointer to a pointer to the first char in a char array, but the fact that one method works and the other doesn't indicates my understanding is incorrect.

Why does one method work and the other doesn't? What am I misunderstanding?

Upvotes: 1

Views: 230

Answers (3)

sje397
sje397

Reputation: 41812

I'll have a shot.

The function strtol wants the address of something it can write to.

When you declare

char *ptr;

you have a variable called ptr and when you pass its address, strtol can write to that location and afterward you can use that value by looking at the contents of the variable.

When you declare

char **ptr;

and just pass its value, first of all you're probably passing an uninitialised value that strtol will try to write to, and secondly, even if you initialise it you're passing just it's contents - strtol will modify the location it points to, not the contents of the variable itself.

Upvotes: 3

atenart
atenart

Reputation: 319

From the man page :

If endptr is not NULL, strtol() stores the address of the first invalid character in *endptr.

In the first case you pass the value of endptr to strtol() which was initialized to 0, so strtol() will not store the address of the first invalid character in *endptr.

In the second case you pass the address of endptr to strtol(), which is not 0, thus it will not return NULL if an invalid character is found.

Upvotes: 0

Nathan Day
Nathan Day

Reputation: 6037

In the first you are not giving a value to your pointer to a pointer, it is an uninitialised value you are passing to strtol, in the second you are defining a pointer and then you are getting the address of it, so you are passing the address of endptr.

Another way to think about it is, the first example you are defining a place in memory that is to holds a pointer to a pointer, but that memory is not set to anything, you are then passing that garbage to strol. The second one you are defining a place in memory that holds a pointer, you are then getting the address of the bit of memory and then passing it to strol.

Upvotes: 1

Related Questions