¿Las cadenas en argv son modificables?


Acabo de escribir un pequeño programa que lee argumentos de la línea de comandos en C, nada demasiado difícil. También los estaba modificando, por ejemplo cambiando el primer carácter del parámetro a mayúsculas.

Sé que no debes modificar literales de cadena ya que puede causar un comportamiento indefinido, así que me preguntaba si las cadenas en el *argv[] son literales que no debes cambiar.

int main(int argc, char *argv[])
Author: cadaniluk, 2016-01-30

3 answers

Del borrador estándar C11 N1570, §5.1.2.2.1 / 2:

Los parámetros argc y argv y las cadenas de caracteres apuntada por el argv array será modificable por el programa, y conservará su último valores entre el inicio y la terminación del programa.

Son modificables. Eso significa que no son literales de cadena.

Pero tenga cuidado : la cita superior solo se refiere a punteros a cadenas , excluyendo la obligatoria puntero nulo en argv[argc]1.
Del borrador estándar C11 N1570, §5.1.2.2.1/2 (igual que el anterior)1:

argv[argc] será un puntero nulo


Notas:

  • Algo con respecto a esta oración:

    Sé que no debes modificar literales de cadena, ya que puede causar comportamiento indefinido [...]

    "puede"? Siempre lo hace. El comportamiento indefinido incluye esperado, como si estuviera bien definido e inesperado comportamiento.


1 Gracias a @negro!

 25
Author: cadaniluk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-01-31 09:55:08
int main(int argc, char *argv[])

argv es una matriz de punteros a char (regla derecha izquierda). Pero las matrices cuando se especifican en argumentos de función se tratan como puntero a tipo de elemento de matriz, por lo que se puede decir que es puntero a puntero a char. Así que de acuerdo con la firma de principal se puede modificar. De lo contrario tendría que ser puntero a puntero a constant char.

También por definición que no es un literal de cadena.

 4
Author: giorgim,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-01-30 16:45:59

Los arrays que soportan las cadenas en argv son modificables.
Pero no tienes forma de saber sus tamaños.

Frunciría el ceño al ver código que (intenta) aumentar el tamaño de las cadenas.

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

En mi máquina, llamar a ese programa con one two three argumentos 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
 3
Author: pmg,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-01-31 10:28:43