2016-01-30 32 views
25

Ho appena scritto un piccolo programma che legge gli argomenti della riga di comando in C, niente di troppo difficile. Li stavo anche modificando, ad esempio cambiando il primo carattere del parametro in maiuscolo.Le stringhe in argv sono modificabili?

So che non è necessario modificare i valori letterali stringa in quanto può causare un comportamento non definito, quindi è stato solo chiedersi se le stringhe nello *argv[] sono letterali che non si dovrebbero modificare.

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

Eventuali duplicati di [Quali sono gli argomenti a main() per?] (Http://stackoverflow.com/questions/ 3734111/what-are-the-argomenti-to-main-for) – user007

+5

Non è un valore letterale. Puoi cambiarlo. – BLUEPIXY

+0

So a cosa servono e cosa significano, mi chiedo solo se fossero letterali. –

risposta

25

Dal progetto di norma C11 N1570, §5.1.2.2.1/2:

I parametri argc e argv e le corde a cui punta l'array argv deve essere modi fi grado dal programma e mantengono i loro valori memorizzati tra l'avvio del programma e la chiusura del programma.

Sono modificabili. Ciò significa che non sono stringhe letterali.

Ma attenti: la citazione in alto si riferisce solo ai puntatori in stringhe, escluso il puntatore nullo obbligatoria a argv[argc] .
Dal progetto di norma C11 N1570, §5.1.2.2.1/2 (come sopra) :

argv[argc] sarà un puntatore nullo


Note:

  • Qualcosa in merito a questa frase:

    So che non si deve modificare stringhe letterali in quanto può causare un comportamento indefinito [...]

    "può"? Lo fa sempre. Il comportamento non definito include il comportamento previsto, come se ben definito e inatteso.


Grazie a @black!

+1

Grazie per la tua risposta, so che causa sempre un comportamento indefinito, credo che dovrei rendere la mia domanda più esplicita, la cambierò ora. –

+1

Che ciò implica che i puntatori stessi possono essere modificati o meno? Cioè si può fare: 'argv [0] = NULL' – 2501

+0

@ 2501 Buona domanda. IMO, "I parametri' argc' e 'argv' e le stringhe puntate dall'array argv devono essere modificabili dal programma [...]" si riferisce solo a 'argc' e' argv' stessi e alle stringhe. Scaverò un po 'e riferirò. – Downvoter

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

argv è array di puntatori a char (right left rule). Ma gli array quando vengono specificati negli argomenti della funzione sono trattati come puntatori al tipo di elemento dell'array, quindi puoi dire che è puntatore al puntatore al char. Quindi, in base alla firma del principale, è possibile modificarlo. Altrimenti doveva essere puntatore al puntatore a constant char.

Anche da definition non è una stringa letterale.

+3

(So che questo è C e C++! = C ma) in C, puoi scrivere 'char * str =" foo ";' e modificare 'str' è ancora un comportamento indefinito. – Downvoter

+0

@cad ok ma rispetto al main avrebbe avuto una strana firma –

+2

@cad Ciò vale anche per C++. La conversione da stringa letterale a 'char *' non è vietata, solo deprecata. – emlai

3

Gli array che supportano le stringhe in argv sono modificabili.
Ma non hai modo di conoscere le loro dimensioni.

Mi vergognerei vedendo il codice che (cerca di) aumentare la dimensione delle stringhe.

#include <stdio.h> 
#include <string.h> 
// 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 string 
     printf("final argv[%d] is %s\n", k - 1, argv[k - 1]); 
    } 
    return 0; 
} 

Sulla mia macchina, chiamando quel programma con one two three argomenti produce

 
original argv[1] is one 
original argv[2] is two 
original argv[3] is three 

first modification to argv[1] is one foo 
first modification to argv[2] is foo foo 
first modification to argv[3] is foo foo 

final argv[3] is foo foo bar 
final argv[2] is foo foo foo bar bar 
final argv[1] is one foo foo foo bar bar bar 
+0

Grazie per questo! Sì, in realtà non aumentavo o diminuivo le dimensioni cambiando semplicemente un carattere per essere maiuscolo o minuscolo. –