tags:

views:

242

answers:

4

Given that scanf has (const char *) in the documentation from Microsoft and the answer to this question what the heck is going when I do the same for (char **) promotion to (const char **)?

Basically why does this compile?

#include <stdio.h>
int main(int argc, char **argv)
{   
    char szArray[50];
    int  i = 0;
    strcpy(szArray,"10");
    /* the following code is upcasting the (char *) to (const char *) */
    sscanf(szArray,"%d",&i);
    return 0;  
}

And why won't this compile?

#include <stdio.h>
void processargs(const char **p)
{ 
}
int main(int argc, char **argv)
{
    processargs(argv);          
    return 0;  
}

Both seem to be doing the same thing to a pointer!

+3  A: 

You're allowed to increase access restriction, you just can't decrease it. Going from a normal pointer to a const pointer is fine, going from a const pointer to a normal pointer is not.

The second example doesn't compile because you're not converting a pointer to a const pointer, you're converting from a pointer to one type (char*) to another (const char*). For example, you can change a char** to a char* const*, but not a const char**.

bradtgmurray
Okay why wont the second example compile then?
ojblass
+11  A: 

char** -> const char ** is dangerous, since you might end up accidentally modifying the underlying const object.

The correct way to write what you want is:

void processargs(const char * const *p)
{ 
}
arul
Bravo... I finally get it.
ojblass
That you can use const this way should be publicized. I don't think that a lot of people know that you can do this.
Dana the Sane
I didn't new to me...
Aaron
i so dense... :(
ojblass
A: 

The first example of yours works, because you're converting rvalues of char* to const char*, which is OK (basically because you cannot assign to rvalues). The second doesn't, because the target of a (non-const) pointer is always a lvalue.

Just try (maybe with the aid of the compiler) which operations you can do with char**, which work with const char**, and think if and what types are interchangeable.

jpalecek
+2  A: 

Check if this clarifies for you:

char * a_mutable = /*...*/;
const char * a_constant = /*...*/;

char **pointer_to_mutable = &a_mutable;   /* ok */

const char **pointer_to_constant = &a_constant;   /* ok */

pointer_to_constant = pointer_to_mutable;   /* oops, are you sure? */

*pointer_to_constant = a_mutable;   /* valid, but will screw things around */

The last line is valid, since pointer_to_constant is a mutable pointer to a mutable pointer to a constant character, but it would break things since you are making a_constant point to a_mutable. That is why you are not allowed to make pointer_to_constant receive the contents of pointer_to_mutable.

Juliano