Программа должна содержать глобальную функцию с именем main , которая является назначенным запуском программы в размещенной среде. Он должен иметь одну из следующих форм:
int main () | (1) |
int main ( int argc , char * argv [] ) | (2) |
/* another implementation-defined form, with int as return type */ | (3) |
argc | — | Отрицательное значение,представляющее собой количество аргументов,переданных программе из среды,в которой выполняется программа. |
argv | — | Указатель на первый элемент массива указателей argc + 1 , последний из которых имеет значение null, а предыдущие, если они есть, указывают на многобайтовые строки с завершающим нулем , которые представляют аргументы, переданные программе из среды выполнения. Если argv[0] не является нулевым указателем (или, что то же самое, если argc > 0 ), он указывает на строку, представляющую имя, используемое для вызова программы, или на пустую строку. |
body | — | Основная функция |
Имена argc и argv произвольны, равно как и представление типов параметров: int main(int ac, char** av) одинаково корректно.
Указатель на функцию в качестве параметра. Передача функции в качестве параметра. С++ Урок #65
Очень распространенная форма main() , определяемая реализацией , имеет третий аргумент (помимо argc и argv ) типа char** , указывающий на массив указателей на переменные среды выполнения .
Explanation
main функция вызывается при запуске программы после инициализации из нелокальных объектов статической продолжительности хранения . Это назначенная точка входа в программу, которая выполняется в hosted окружение (то есть,с операционной системой).Вход указывает на freestanding программы (системный загрузчик,ядра ОС и т.д.)определяются реализацией.
Параметры двухпараметрической формы основной функции позволяют передавать произвольные многобайтовые символьные строки из среды исполнения (их обычно называют аргументы командной строки ), указатели argv[1] . argv[argc — 1] указывают на первые символы в каждой из этих строк. argv[0] (если не нулевой) — это указатель на начальный символ многобайтовой строки с завершающим нулем, которая представляет имя, используемое для вызова самой программы (или пустая строка «» , если это не поддерживается средой выполнения). ). Строки поддаются изменению, хотя эти изменения не распространяются обратно в среду выполнения: их можно использовать, например, с std::strtok . Размер массива, на который указывает argv , не меньше argc + 1 , а последний элемент argv[argc] гарантированно будет нулевым указателем.
main функция имеет несколько специальных свойств:
1)Она не может быть использована нигде в программе.
а)в частности,его нельзя назвать рекурсивным.
б)его адрес не может быть указан
2) Оно не может быть предопределено и не может быть перегружено: по сути, имя main в глобальном пространстве имен зарезервировано для функций (хотя его можно использовать для именования классов, пространств имен, перечислений и любых объектов в неглобальном пространстве имен, за исключением того, что объект с именем main не может быть объявлен сосвязью языка C в любом пространстве имен.
Аргументы функции main
3) Он не может быть определен как удаленный или (начиная с С++ 11) объявленный с какой-либо привязкой к языку, , constexpr (начиная с С++ 11), consteval (начиная с С++ 20), inline или static .
4) Тело функции main не обязательно должно содержать оператор return : если управление достигает конца main , не встречая оператора return, результатом является выполнение return 0; ,
5) Выполнение возврата (или неявного возврата по достижении конца main) эквивалентно первому нормальному выходу из функции (что уничтожает объекты с автоматическим временем хранения) и последующему вызову std::exit с тем же аргументом, что и аргумент возвращения . _ ( std::exit затем уничтожает статические объекты и завершает работу программы).
6) Тип возврата основной функции не может быть выведен ( auto main() | (since C++14) |
7) Основная функция не может быть сопрограммой . | (since C++20) |
Notes
Если основная функция определена с помощью функции-try-block , то исключения, создаваемые деструкторами статических объектов (которые уничтожаются подразумеваемым std::exit ), им не перехватываются.
Способ, которым аргументы, заданные в командной строке ОС, преобразуются в многобайтовые массивы символов, на которые ссылается argv , может включать в себя обработку, определяемую реализацией:
- Анализ аргументов командной строки C++ MSDN
- Введение в оболочку POSIX
Example
Демонстрирует,как информировать программу о том,где ей искать входные данные и куда записывать результаты.
Возможный вызов: ./convert table_in.dat table_out.dat .
#include #include #include int main(int argc, char *argv[]) < std::cout «argc = hljs-string»>’n’; for(int ndx<>; ndx != argc; ++ndx) < std::cout «argv[» << ndx «] = hljs-built_in»>quoted(argv[ndx]) ‘n’; > std::cout «argv[» << argc «] = hljs-built_in»>static_castvoid*>(argv[argc]) ‘n’; /*. */ return argc == 3 ? EXIT_SUCCESS : EXIT_FAILURE; // необязательное возвращаемое значение >
argc == 3 argv[0] == «./convert» argv[1] == «table_in.dat» argv[2] == «table_out.dat» argv[3] == 0
Defect reports
Следующие отчеты о дефектах,изменяющих поведение,были применены ретроактивно к ранее опубликованным стандартам C++.
CWG 1003 | C++98 | для формы (2),определения,имена параметров которых которые не являются argc (1-й параметр) и argv (2-й параметр) не требовалось поддерживать |
необходимо поддерживать все допустимые имена параметров |
CWG 1886 | C++98 | главная функция может быть объявлена с привязкой к языку | prohibited |
CWG 2479 | C++20 | основная функция может быть объявлена consteval | prohibited |
See also
Документация C для main функции |
C++
Инициализация списка (с C++11)
Инициализирует объект из списка скрепленных фигур.
Name lookup
Поиск имени-это процедура,которая,когда встречается в программе,ассоциируется с объявлением,которое ввело Например,для компиляции std::cout std::endl;,
Функции нестатического члена
Нестатическая функция-член-это функция,объявленная в спецификации класса без спецификатора friend.
Member templates
Объявления шаблонов (класс, функция и переменные (начиная с C++14)) могут появляться внутри спецификации члена любой структуры или объединения, которые не являются локальными классами.
Источник: runebook.dev
Как стать программистом
Сегодняшний наш урок будет посвящен пользовательским функциям, который программист пишет самостоятельно. И опять мне улыбнулась удача. Когда я отвечал на ваши комментарии к прошлым урокам, нашел хороший пример для иллюстрации использования функций в Си. Про полезность хороший примеров я уже говорил. Итак начнем.
Прочитайте улучшенную версию этого урока «Простые пользовательские функции».
- Ещё более доступное объяснение
- Дополнительные материалы
- 10 задач на программирование с автоматической проверкой решения
В домашнем задании к уроку №5 я просил вас, написать программу которая решает уравнение ах=b в целых числах относительно х. Что многие успешно сделали. Разберем теперь другую сторону вопроса. Пусть нам надо проверить одну такую программу. Вот её код.
Листинг 10.1
int main( void )
if (b%a!=0) printf( «no solutionn» );
printf( «%dn» ,b/a);
Теперь подумаем как вообще должно решаться такое уравнение и подберем к нему набор тестов.
ах=b следовательно х=b/a. Так как решение в целых числах, то при делении b на a не должно получаться остатка.
Получаем несколько вариантов решения.
1) а=0 и b=0 х любое число.т.е. программа должна вывести many solution.
2) a=0 и b!=0 решений нет. Программа должна ответить no solution
3) b делится на а без остатка, то это и b/a решение.
4) b делится на а с остатком. Программа должна вывести no solution
Теперь подберем проверочные значения для каждого случая.
Теперь нам надо проверить нашу программу на всех этих данных и если в ответе получается
1. many solution
2. no solution
4. no solution
то программа написана верно.
Разберемся как можно сделать это используя те знания, которые у нас уже есть за 9 уроков.
1.5.3. Передача параметров функции main
Функция main, с которой начинается выполнение СИ-программы, может быть определена с параметрами, которые передаются из внешнего окружения например, из командной строки. Во внешнем окружении действуют свои правила представления данных, а точнее, все данные представляются в виде строк символов.
Для передачи этих строк в функцию main используются два параметра, первый параметр служит для передачи числа передаваемых строк, второй для передачи самих строк. Общепринятые (но не обязательные) имена этих параметров argc и argv. Параметр argc имеет тип int, его значение формируется из анализа командной строки и равно количеству слов в командной строке, включая и имя вызываемой программы (под словом понимается любой текст не содержащий символа пробел). Параметр argv это массив указателей на строки, каждая из которых содержит одно слово из командной строки. Если слово должно содержать символ пробел, то при записи его в командную строку оно должно быть заключено в кавычки.
Функция main может иметь и третий параметр, который принято называть argp, и который служит для передачи в функцию main параметров операционной системы (среды) в которой выполняется СИ-программа.
int main (int argc, char *argv[], char *argp[])
Если, например, командная строка СИ-программы имеет вид:
A:>cprog working ‘C program’ 1
то аргументы argc, argv, argp представляются в памяти как показано в схеме на рис.1.
1 2 3 4 5 6 7 8 9 10 11 12 13
argc [ 4 ] argv [ ]— [ ]— [A:cprog.
exe ] [ ]— [working ] [ ]— [C program ] [ ]— [1 ] [NULL] argp [ ]— [ ]— [path=A:;C:\0] [ ]— [lib=D:LIB ] [ ]— [include=D:INCLUDE ] [ ]— [conspec=C:COMMAND.COM] [NULL] Рис.1. Схема размещения параметров командной строки
argc [ 4 ] argv [ ]—> [ ]—> [A:cprog.exe ] [ ]—> [working ] [ ]—> [C program ] [ ]—> [1 ] [NULL] argp [ ]—> [ ]—> [path=A:;C:\0] [ ]—> [lib=D:LIB ] [ ]—> [include=D:INCLUDE ] [ ]—> [conspec=C:COMMAND.COM] [NULL] Рис.1. Схема размещения параметров командной строки
Операционная система поддерживает передачу значений для параметров argc, argv, argp, а на пользователе лежит ответственность за передачу и использование фактических аргументов функции main.
Следующий пример представляет программу печати фактических аргументов, передаваемых в функцию main из операционной системы и параметров операционной системы.
1 2 3 4 5 6 7 8 9 10 11 12 13 14
Пример: 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 функции с такими же именами, но не выполняющие никаких действий (заглушки). Начало программы в этом случае будет иметь вид:
1 2 3 4 5 6 7 8 9 10 11 12 13
_setargv() { return ; /* пустая функция */ } -seteuv() { return ; /* пустая функция */ } int main() { /* главная функция без аргументов */ . . renurn (0); }
В приведенной программе при вызове библиотечных функций _setargv и _seteuv будут использованы функции помещенные в программу пользователем и не выполняющие никаких действий. Это заметно снизит размер получаемого exe-файла.