Подтвердить что ты не робот

Могут ли быть изменены строки в argv?

Я написал небольшую программу, которая читает аргументы командной строки на C, ничего сложного. Я также изменял их, например, меняя первый символ параметра на верхний.

Я знаю, что вы не должны изменять строковые литералы, так как это может вызвать поведение undefined, поэтому просто интересно, являются ли строки в *argv[] литералами, которые вы не должны изменять.

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

Ответ 1

Из стандартного черновика C11 N1570, §5.1.2.2.1/2:

Параметры argc и argv и строки, на которые указывает argvмассив должен быть модифицирован программой и сохранять их последние сохраненные значений между запуском программы и завершением программы.

Они изменяемы. Это означает, что они не являются строковыми литералами.

Но будьте осторожны: верхняя цитата относится только к указателям к строкам, за исключением обязательного нулевого указателя в argv[argc] 1. < ш > Из стандартного проекта C11 N1570, §5.1.2.2.1/2 (то же, что и выше) 1:

argv[argc] должен быть нулевым указателем


Примечания:

  • Что-то в этом предложении:

    Я знаю, что вы не должны изменять строковые литералы, поскольку это может вызвать undefined поведение [...]

    "может"? Это всегда. undefined поведение включает ожидаемое, как бы корректное и неожиданное поведение.


1 Благодаря @black!

Ответ 2

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

argv - массив указателей на char (правое правое правило). Но массивы, заданные в аргументах функции, рассматриваются как указатель на тип элемента массива, поэтому вы можете сказать, что это указатель на указатель на char. Таким образом, согласно сигнатуре основного, вы можете его изменить. В противном случае он должен был быть указателем на указатель на constant char.

Также определение, которое не является строковым литералом.

Ответ 3

Массивы, поддерживающие строки в argv, могут быть изменены.
Но у вас нет способа узнать их размеры.

Я бы не хотел видеть код, который (пытается) увеличить размер строк.

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

На моей машине вызов этой программы с аргументами one two three вызывает

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