Linux программирование в примерах | страница 33
>{ {
>... ...
>} }
Практически между двумя этими объявлениями нет разницы, хотя первое концептуально более понятно: >argc
является массивом указателей на символы. А второе определение технически более корректно, это то, что мы используем. На рис. 2.2 изображена эта ситуация.
Рис. 2.2. Память для >argc
По соглашению, >argv[0]
является именем программы. (Детали см. в разделе 9.1.4.3. «Имена программ и >argv[0]
».) Последующие элементы являются аргументами командной строки. Последним элементом массива >argv
является указатель >NULL
.
>argc
указывает, сколько имеется аргументов; поскольку в С индексы отсчитываются с нуля, выражение '>argv[argc] == NULL
' всегда верно. Из-за этого, особенно в коде для Unix, вы увидите различные способы проверки окончания списка аргументов, такие, как цикл с проверкой, что счетчик превысил >argc
, или '>argv[i] == 0
', или '>*argv != NULL
' и т.д. Они все эквивалентны.
2.2.1. Программа >echo
V7
Возможно, простейшим примером обработки командной строки является программа V7 >echo,
печатающая свои аргументы в стандартный вывод, разделяя их пробелами и завершая символом конца строки. Если первым аргументом является >-n
, завершающий символ новой строки опускается. (Это используется для приглашений из сценариев оболочки.) Вот код[28]:
>1 #include
>2
>3 main(argc, argv) /*int main(int argc, char **argv)*/
>4 int argc;
>5 char *argv[];
>6 {
>7 register int i, nflg;
>8
>9 nflg = 0;
>10 if (argc > 1 && argv[1][0] == && argv[1][1] == 'n') {
>11 nflg++;
>12 argc--;
>13 argv++;
>14 }
>15 for (i=1; i
>16 fputs(argv[i], stdout);
>17 if (i < argc-1)
>18 putchar(' ');
>19 }
>20 if (nflg == 0)
>21 putchar('\n');
>22 exit(0);
>23 }
Всего 23 строки! Здесь есть два интересных момента. Во-первых, уменьшение >argc
и одновременное увеличение >argv
(строки 12 и 13) являются обычным способом пропуска начальных аргументов. Во-вторых, проверка наличия >-n
(строка 10) является упрощением. >-no-newline-at-the-end
также работает. (Откомпилируйте и проверьте это!)
Ручной разбор опций обычен для кода V7, поскольку функция >getopt()
не была еще придумана.
Наконец, здесь и в других местах по всей книге, мы видим использование ключевого слова register. Одно время это ключевое слово давало компилятору подсказку, что данная переменная должна по возможности размещаться в регистре процессора. Теперь это ключевое слово устарело; современные компиляторы все основывают размещение переменных в регистрах на анализе исходного кода, игнорируя ключевое слово