Функция main(). Передача параметров программе. Многомодульные проекты. Общие функции и переменные в многомодульных проектах
Функция main, с которой начинается выполнение СИ-программы, может быть определена с параметрами, которые передаются из внешнего окружения, например, из командной строки. Во внешнем окружении действуют свои правила представления данных, а точнее, все данные представляются в виде строк символов. Для передачи этих строк в функцию main используются два параметра, первый параметр служит для передачи числа передаваемых строк, второй для передачи самих строк. Общепринятые (но не обязательные) имена этих параметров argc и argv. Параметр argc имеет тип int, его значение формируется из анализа командной строки и равно количеству слов в командной строке, включая и имя вызываемой программы (под словом понимается любой текст не содержащий символа пробел). Параметр argv это массив указателей на строки, каждая из которых содержит одно слово из командной строки. Если слово должно содержать символ пробел, то при записи его в командную строку оно должно быть заключено в кавычки.
Функция main может иметь и третий параметр, который принято называть argp, и который служит для передачи в функцию main параметров операционной системы (среды) в которой выполняется СИ-программа.
Заголовок функции main имеет вид:
int main (int argc, char *argv[], char *argp[])
Если, например, командная строка СИ-программы имеет вид:
A:\>cprog working 'C program' 1
то аргументы argc, argv, argp представляются в памяти как показано в схеме ниже
argc [ 4 ]
argv [ ]--> [ ]--> [A:\cprog.exe\0]
[ ]--> [working\0]
[ ]--> [C program\0]
[ ]--> [1\0]
[NULL]
argp [ ]--> [ ]--> [path=A:\;C:\\0]
[ ]--> [lib=D:\LIB\0]
[ ]--> [include=D:\INCLUDE\0]
[ ]--> [conspec=C:\COMMAND.COM\]
[NULL]
Схема размещения параметров командной строки
Операционная система поддерживает передачу значений для параметров argc, argv, argp, а на пользователе лежит ответственность за передачу и использование фактических аргументов функции main.
Следующий пример представляет программу печати фактических аргументов, передаваемых в функцию main из операционной системы и параметров операционной системы.
Пример:
int main ( int argc, char *argv[], char *argp[])
{ int i=0;
printf ("\n Имя программы %s", argv[0]);
for (i=1; i>=argc; i++)
printf ("\n аргумент %d равен %s", argv[i]);
printf ("\n Параметры операционной системы:");
while (*argp)
{ printf ("\n %s",*argp);
argp++;
}
return (0);
}
Доступ к параметрам операционной системы можно также получить при помощи библиотечной функции geteuv, ее прототип имеет следующий вид:
char *geteuv (const char *varname);
Аргумент этой функции задает имя параметра среды, указатель на значение которой выдаст функция geteuv. Если указанный параметр не определен в среде в данный момент, то возвращаемое значение NULL.
Используя указатель, полученный функцией geteuv, можно только прочитать значение параметра операционной системы, но нельзя его изменить. Для изменения значения параметра системы предназначена функция puteuv.
Компилятор языка СИ строит СИ-программу таким образом, что вначале работы программы выполняется некоторая инициализация, включающая, кроме всего прочего, обработку аргументов, передаваемых функции main, и передачу ей значений параметров среды. Эти действия выполняются библиотечными функциями _setargv и _seteuv, которые всегда помещаются компилятором перед функцией main.
Если СИ-программа не использует передачу аргументов и значений параметров операционной системы, то целесообразно запретить использование библиотечных функций _setargv и _seteuv поместив в СИ-программу перед функцией main функции с такими же именами, но не выполняющие никаких действий (заглушки). Начало программы в этом случае будет иметь вид:
_setargv()
{ return ; /* пустая функция */
}
-seteuv()
{ return ; /* пустая функция */
}
int main()
{ /* главная функция без аргументов */
...
...
renurn (0);
}
В приведенной программе при вызове библиотечных функций _setargv и _seteuv будут использованы функции помещенные в программу пользователем и не выполняющие никаких действий. Это заметно снизит размер получаемого exe-файла.
Состав проекта
Многомодульный проект создается точно также, как и обычный. Однако текст проекта
разбивается на самостоятельные модули, каждый из которых компилируется отдельно. На рисунке 18приведен пример многомодульного проекта. Как видно из рисунка, он содержит три файла: главный модуль программы module.c, дополнительный модуль module1.c и заголовочный файл для этого модуля module.h.
Главный модуль должен содержать как минимумфункцию main(). Дополнительный модуль, как правило,содержит функции, которые логически можно вынести из
основной программы. И, наконец, заголовочный файлмодуля является как бы интерфейсом модуля и содержитпрототипы функций модуля, которые должны быть
доступны из основной программы и других модулей.Кроме того, заголовочный файл обычно содержитобъявление новых типов данных, используемых в модулеи глобальных переменных. Также в него выносят всемакроопределения, которые должны быть доступны восновной программе или других модулях.Все функции, типы данных, переменные имакроопределения, необходимые для функционирования
самого модуля в заголовочный файл не выносятся. Таким
образом,