Могут ли быть изменены строки в argv?
Я написал небольшую программу, которая читает аргументы командной строки на C, ничего сложного. Я также изменял их, например, меняя первый символ параметра на верхний.
Я знаю, что вы не должны изменять строковые литералы, так как это может вызвать поведение undefined, поэтому просто интересно, являются ли строки в *argv[]
литералами, которые вы не должны изменять.
int main(int argc, char *argv[])
Ответы
Ответ 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