#c #pointers #argv #kernighan-and-ritchie
Вопрос:
Этот вопрос касается значения некоторого синтаксиса из Главы 5, раздел 5.10 «Язык программирования C» Kamp;R2, стр. 117.
Ранее в этой главе книги Kamp;R2 они объясняли, что имя массива является указателем на его первый элемент; поэтому я знаю, что argv является указателем на первый аргумент командной строки, например ./Exercise5-10
.
Как работает синтаксис в циклах while этой программы? (* argv)[0]
Я знаю, что получает первый символ строки: argv, естественно, указывает на индекс 0, который является именем программы, и увеличивается до следующего символа* или строки, затем на него снимается ссылка, *
и его первый символ доступен с помощью обозначения [0]. Я просто не понимаю во внутреннем цикле, как * argv[0]
происходит разбор строки.
Я даже заглянул в книгу заранее, и объяснение все еще неясно. Для меня * argv[0]
сначала идет 0-й char*
в argv, название программы. Затем он увеличивается до следующей строки -x
или в любом другом случае. Затем снова отменяется ссылка, что приводит к первому символу.
Я этого не понимаю и хотел бы получить дополнительные разъяснения.
#include <stdio.h>
#include <string.h>
#define MAXLINE 1000
int getinput(char s[], int lim);
/* find: print lines that match pattern from 1st arg */
int main(int argc, char *argv[])
{
char line[MAXLINE];
long lineno = 0;
int c, except = 0, number = 0, found = 0;
while (--argc > 0 amp;amp; (* argv)[0] == '-')
while ((c = * argv[0]))
switch (c)
{
case 'x':
except = 1;
break;
case 'n':
number = 1;
break;
default:
printf("find: illegal option %cn", c);
argc = 0;
found = -1;
break;
}
if (argc != 1)
printf("Usage: find -x -n patternn");
else
while (getinput(line, MAXLINE) > 0)
{
lineno ;
if ((strstr(line, *argv) != NULL) != except)
{
printf("%ld:", lineno);
printf("%s", line);
found ;
}
}
return found;
}
/* getline: read a line into s, return length */
int getinput(char s[], int lim)
{
int c, i;
for (i = 0; i < lim-1 amp;amp; (c = getchar()) != EOF amp;amp; c != 'n'; i)
s[i] = c;
if (c == 'n')
{
s[i] = c;
i;
}
s[i] = '';
return i;
}
Комментарии:
1. Это может помочь узнать, что
[]
имеет более высокий приоритет, чем. Поэтому
argv[0]
увеличивает и возвращает то, чтоargv[0]
удерживается, а неargv
.2. Примечание:
argv
представляет собой массив указателей на строки. Поэтому приращениеargv
указывает на следующую полосу. Разыменованиеargv
возвращает указатель на «текущий» строковый параметр
Ответ №1:
while (--argc > 0 amp;amp; (* argv)[0] == '-')
«пока осталось несколько аргументов, и первый символ следующего аргумента-это тире (и, кстати, приращение argv
, указывающее на этот аргумент)». Это неявно игнорирует argv[0]
, что является именем программы, так как первое, что она делает, — это увеличивает argv
, чтобы указать на (то, что было раньше) argv[1]
.
while ((c = * argv[0]))
«хотя в аргументе, на который указывает argv[0]
(т. Е. Мы не достигли нулевого терминатора), осталось несколько символов, и, кстати, увеличьте этот указатель, но также сохраните указанный символ как c
«. Опять же, это игнорирует первый символ аргумента (который, как мы уже знаем, является a '-'
) путем увеличения перед разыменованием.
switch (c)
сделайте что — нибудь с каждым символом флага. Это использует довольно старый стиль флага Unix, где флаги имеют односимвольные имена, и -abc
это то же самое, -a -b -c
что .
Это код в место, изменяет argc
, argv
, и каждый элемент argv
, который содержит флаг, который будет рассмотрен довольно небрежно и запутанным сегодня, но в 1970 пространства был на вес золота (типичный машины, с целью, вероятно, есть несколько десятков килобайт памяти, и иногда даже меньше), и делая копию чего-нибудь, когда будет не нужен оригинальный снова сочли бы немного грешной. Он оставляет программу в состоянии, в котором argc
указано количество аргументов без флага, и argv[0]
указывает на первый аргумент без флага.