2009-04-19 5 views
4

Étant donné que scanf a (const char *) dans le documentation from Microsoft et la réponse à this question que diable se passe-t-il quand je fais de même pour la promotion (char **) en (const char **)?Pourquoi cela permet-il la promotion de (char *) vers (const char *)?

Fondamentalement pourquoi cela compile-t-il?

#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; 
} 

Et pourquoi ne pas compiler?

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

Les deux semblent faire la même chose à un pointeur!

+1

vous ne comprenez pas une chose: si T -> U fonctionne, cela ne signifie pas que T * -> U * fonctionne. juste un simple: double a = 4;/* int -> double */int p; double * dp = & p;/* int * -> double * ?? */ –

+0

Je ne change pas les types ici ... les deux ensembles sont des pointeurs. – ojblass

+0

S'il vous plaît fermer l'autre et pas celui-ci ... – ojblass

Répondre

12

char** -> const char ** est dangereux, car vous risquez de modifier accidentellement l'objet const sous-jacent.

La bonne façon d'écrire ce que vous voulez est:

void processargs(const char * const *p) 
{ 
} 
+0

Bravo ... Je l'ai enfin compris. – ojblass

+3

Que vous pouvez utiliser const de cette façon devrait être rendu public. Je ne pense pas que beaucoup de gens savent que vous pouvez le faire. –

+0

Je ne l'ai pas nouveau pour moi ... – Aaron

3

Vous êtes autorisé à augmenter la restriction d'accès, vous ne pouvez pas la diminuer. Passer d'un pointeur normal à un pointeur constant, c'est bien, passer d'un pointeur const à un pointeur normal ne l'est pas.

Le deuxième exemple ne compile pas car vous ne convertissez pas un pointeur en pointeur const, vous passez d'un pointeur à un type (char*) à un autre (const char*). Par exemple, vous pouvez remplacer un char** par un char* const*, mais pas un const char**.

+0

Ok, pourquoi ne pas compiler alors le deuxième exemple? – ojblass

0

Le premier exemple de vos travaux, parce que vous convertissez rvalues ​​ de char*-const char*, qui est OK (essentiellement parce que vous ne pouvez pas affecter aux valeurs). La seconde ne le fait pas, car la cible d'un pointeur (non-const) est toujours une lvalue. Essayez simplement (peut-être avec l'aide du compilateur) quelles opérations vous pouvez faire avec char**, qui fonctionnent avec const char**, et pensez si et quels types sont interchangeables.

2

Vérifiez si cela clarifie pour vous:

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 */ 

La dernière ligne est valide, car pointer_to_constant est un pointeur mutable à un pointeur mutable à un caractère constant, mais il briserait les choses puisque vous faites a_constant points à a_mutable. C'est pourquoi vous n'êtes pas autorisé à faire pointer_to_constant recevoir le contenu de pointer_to_mutable.