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. Одно время это ключевое слово давало компилятору подсказку, что данная переменная должна по возможности размещаться в регистре процессора. Теперь это ключевое слово устарело; современные компиляторы все основывают размещение переменных в регистрах на анализе исходного кода, игнорируя ключевое слово