Les chaînes dans argv sont-elles modifiables?

Je viens d’écrire un petit programme qui lit les arguments de ligne de commande en C, rien de bien difficile. Je les modifiais également, en modifiant par exemple le premier caractère du paramètre en majuscule.

Je sais que vous ne devez pas modifier les littéraux de chaîne car cela peut entraîner un comportement indéfini. Je me demandais donc simplement si les chaînes dans *argv[] étaient des littéraux que vous ne devriez pas changer.

 int main(int argc, char *argv[]) 

Du projet de norme C11 N1570, §5.1.2.2.1 / 2:

Les parameters argc et argv et les chaînes pointées par le tableau argv doivent être modifiables par le programme et conserver leurs dernières valeurs stockées entre le démarrage et la fin du programme.

Ils sont modifiables. Cela signifie qu’ils ne sont pas des littéraux de chaîne.

Mais faites attention : la citation supérieure ne fait référence qu’aux pointeurs sur des chaînes , à l’exclusion du pointeur null obligatoire de argv[argc] 1 .
Du projet de norme C11 N1570, §5.1.2.2.1 / 2 (comme ci-dessus) 1 :

argv[argc] doit être un pointeur nul


Remarques:

  • Quelque chose à propos de cette phrase:

    Je sais que vous ne devriez pas modifier les littéraux de chaîne car cela peut provoquer un comportement indéfini […]

    “pouvez”? C’est toujours le cas. Le comportement non défini inclut le comportement attendu, comme s’il était bien défini, et inattendu.


1 Merci à @black!

 int main(int argc, char *argv[]) 

argv est un tableau de pointeurs sur char ( règle de droite à gauche ). Mais les tableaux, lorsqu’ils sont spécifiés dans les arguments de la fonction, sont traités comme un pointeur sur un type d’élément de tableau. Vous pouvez donc dire qu’il s’agit d’un pointeur à l’autre. Donc, en fonction de la signature du principal, vous pouvez le modifier. Sinon, il fallait que ce soit un pointeur à l’autre.

Aussi, par définition, ce n’est pas un littéral de chaîne.

Les tableaux qui supportent les chaînes dans argv sont modifiables.
Mais vous n’avez aucun moyen de connaître leurs tailles.

Je froncerais les sourcils en voyant un code qui (essaye) d’augmenter la taille des chaînes.

 #include  #include  // this program may behave erraticaly int main(int argc, char **argv) { for (int k = 1; k < argc; k++) { printf("original argv[%d] is %s\n", k, argv[k]); } printf("\n"); for (int k = 1; k < argc; k++) { strcat(argv[k], " foo"); // add foo to each argv string printf("first modification to argv[%d] is %s\n", k, argv[k]); } printf("\n"); for (int k = argc; k > 1; k--) { strcat(argv[k - 1], " bar"); // add bar to each argv ssortingng printf("final argv[%d] is %s\n", k - 1, argv[k - 1]); } return 0; } 

Sur ma machine, appeler ce programme avec one two three arguments produit

 argv original [1] est un
 argv original [2] est deux
 argv original [3] est trois

 la première modification de argv [1] est un foo
 la première modification de argv [2] est foo foo
 la première modification de argv [3] est foo foo

 argument final [3] est foo foo bar
 argument final [2] est foo foo foo bar bar
 argument final [1] est un foo foo foo bar bar bar