для чего нужен int main в c
BestProg
Содержание
Поиск на других ресурсах:
Функция Main() – это специальная функция, которая предназначена для начала выполнения любой программы и имеет следующие особенности применения:
2. Способы объявления функции Main()
Функция Main() может быть объявлена одним из четырех возможных способов, перечисленных ниже.
Способ 1. Функция не возвращает значения и не получает параметров. Общая форма функции Main() в этом случае следующая:
Способ 2. Функция возвращает целочисленное значение и не получает параметров. В этом случае общая форма функции следующая
Способ 3. Функция не возвращает значения, но получает параметры. Параметрами функции Main() может быть массив строк. В этом случае общая форма функции следующая:
Способ 4. Функция возвращает целочисленное значение и получает параметры. Общая форма объявления функции следующая
3. Модификаторы доступа, которые могут применяться с функцией Main()
Функция Main() может быть объявлена с двумя модификаторами доступа:
4. Зачем в качестве параметров в функцию Main() передается массив строк?
В качестве параметров в любую программу (функцию Main() ) вызывающий процесс (операционная система) может передать только строку символов. Если эта строка содержит слова, которые разделены символом пробел, то эта строка разбивается на массив строк.
Например. Пусть сделан вызов программы с именем Project1.exe следующим образом:
то функция Main() программы Project1.exe получит следующий массив входных параметров
то есть, для следующего объявления функции
значения переменной args будут следующими:
5. Пример, который демонстрирует применение параметров в функции Main()
В примере продемонстрирован вывод массива параметров на экран. Программа создана по шаблону Console Application.
Результат выполнения программы ConsoleApp1.exe для строки
имеет следующий вид
как показано на рисунке 1.
Рисунок 1. Команда вызова свойств проекта
Рисунок 2. Установка аргументов командной строки
7. Каким образом в функцию Main() передать строку, которая содержит пробелы?
Бывают случаи, когда в функцию Main() нужно передать строку как один параметр. Но эта строка может содержать пробелы. В этом случае строку нужно заключить в двойные кавычки. Все что размещается между двойными кавычками не разбивается по параметрам.
Например. Пусть в функцию Main() для приложения с именем ConsoleApp1.exe нужно передать два параметра-строки:
В этом случае, вызов ConsoleApp1.exe из другого процесса (например, из командной строки) будет следующим:
В этом случае в функцию Main() будут переданы следующие значения массива args :
Важно помнить, что метод GetCommandLineArgs() возвращает массив параметров на один больше. Первым параметром, который возвращает метод (под индексом 0) идет полное имя к текущему выполняемому файлу.
9. Определение полного имени файла выполняемой программы
Нижеследующий фрагмент кода демонстрирует вывод полного имени файла текущей программы
Несколько подробностей о функции main
Однажды заинтересовался, содержимым стека функции main процесса в linux. Провел некоторые изыскания и теперь представляю вам результат.
Варианты описания функции main:
1. int main()
2. int main(int argc, char **argv)
3. int main(int argc, char **argv, char **env)
4. int main(int argc, char **argv, char **env, ElfW(auxv_t) auxv[])
5. int main(int argc, char **argv, char **env, char **apple)
argc — число параметров
argv — нуль-терминальный массив указателей на строки параметров командной строки
env — нуль-терминальный массив указателей на строки переменных окружения. Каждая строка в формате ИМЯ=ЗНАЧЕНИЕ
auxv — массив вспомогательных значение (доступно только для PowerPC [1])
apple — путь к исполняемому файлу (в MacOS и Darwin [2])
Вспомогательный вектор — массив с различной дополнительной информацией, такой как эффективный идентификатор пользователя, признак setuid бита, размер страницы памяти и т.п.
Далее о том как получить массив вспомогательных значений для i386 и x86_64, а также об остальном содержимом «сегмента» стека.
Размер сегмента стека можно глянуть в файле maps:
cat /proc/10918/maps
…
7ffffffa3000-7ffffffff000 rw-p 00000000 00:00 0 [stack]
…
Перед тем, как загрузчик передаст управление в main, он инициализирует содержимое массивов параметров командной строки, переменных окружения, вспомогательный вектор.
После инициализации верхняя часть стека выглядит примерно так, для 64битной версии.
Старший адрес сверху.
1. | 0x7ffffffff000 | Верхняя точка сегмента стека. Обращение вызывает segfault | |||
0x7ffffffff0f8 | NULL | void* | 8 | 0x00′ | |
2. | filename[0] | char | 1+ | «/tmp/a.out» | |
char | 1 | 0x00 | |||
. | |||||
env[1][0] | char | 1 | 0x00 | ||
. | |||||
char | 1 | 0x00 | |||
3. | 0x7fffffffe5e0 | env[0][0] | char | 1 | .. |
char | 1 | 0x00 | |||
. | |||||
argv[1][0] | char | 1 | 0x00 | ||
. | |||||
char | 1 | 0x00 | |||
4. | 0x7fffffffe5be | argv[0][0] | char | 1+ | «/tmp/a.out» |
5. | Массив случайной длины | ||||
6. | данные для auxv | void*[] | 48′ | ||
AT_NULL | Elf64_auxv_t | 16 | |||
. | |||||
auxv[1] | Elf64_auxv_t | 16 | |||
7. | auxv[0] | Elf64_auxv_t | 16 | Ex.: | |
NULL | void* | 8 | 0x00 | ||
. | |||||
env[1] | char* | 8 | |||
8. | 0x7fffffffe308 | env[0] | char* | 8 | 0x7fffffffe5e0 |
NULL | void* | 8 | 0x00 | ||
. | |||||
argv[1] | char* | 8 | |||
9. | 0x7fffffffe2f8 | argv[0] | char* | 8 | 0x7fffffffe5be |
10. | 0x7fffffffe2f0 | argc | long int | 8′ | число аргументов + 1 |
11. | Локальные переменные и аргументы, функций вызываемых до main | ||||
12. | Локальные переменные main | ||||
13. | 0x7fffffffe1fc | argc | int | 4 | число аргументов + 1 |
0x7fffffffe1f0 | argv | char** | 8 | 0x7fffffffe2f8 | |
0x7fffffffe1e8 | env | char** | 8 | 0x7fffffffe308 | |
14. | Переменные локальных функций |
‘ — описания полей в документах не нашел, но в дампе явно видны.
Для 32 битов не проверял, но скорее всего достаточно только разделить размеры на два.
Вспомогательный вектор
Для i386 и x86_64 нельзя получить адрес первого элемента вспомогательного вектора, однако содержимое этого вектора можно получить другими способами. Один из них — обратиться к области памяти, лежащей сразу за массивом указателей на строки переменных окружения.
Это должно выглядеть примерно так:
Структуры Elf<32,64>_auxv_t описаны в /usr/include/elf.h. Функции заполнения структур в linux-kernel/fs/binfmt_elf.c
Второй способ получить содержимое вектора:
hexdump /proc/self/auxv
Самый удобочитаемое представление получается установкой переменной окружения LD_SHOW_AUXV.
LD_SHOW_AUXV=1 ls
AT_HWCAP: bfebfbff //возможности процессора
AT_PAGESZ: 4096 //размер страницы памяти
AT_CLKTCK: 100 //частота обновления times()
AT_PHDR: 0x400040 //информация о заголовке
AT_PHENT: 56
AT_PHNUM: 9
AT_BASE: 0x7fd00b5bc000 //адрес интерпретатора, то бишь ld.so
AT_FLAGS: 0x0
AT_ENTRY: 0x402490 //точка входа в программу
AT_UID: 1000 //идентификаторы пользователя и группы
AT_EUID: 1000 //номинальные и эффективные
AT_GID: 1000
AT_EGID: 1000
AT_SECURE: 0 //поднят ли setuid флаг
AT_RANDOM: 0x7fff30bdc809 //адрес 16 случайных байт,
генерируемых при запуске
AT_SYSINFO_EHDR: 0x7fff30bff000 //указатель на страницу, используемую для
//системных вызовов
AT_EXECFN: /bin/ls
AT_PLATFORM: x86_64
Слева — название переменной, справа значение. Все возможные названия переменных и их описание можно глянуть в файле elf.h. (константы с префиксом AT_)
Возвращение из main()
После инициализации контекста процесса управление передается не в main(), а в функцию _start().
main() вызывает уже из __libc_start_main. Эта последняя функция имеет интересную особенность — ей передается указатель на функцию, которая должна быть выполнена после main(). И указатель этот передается естественно через стек.
Вообще аргументы __libc_start_main имеют вид, согласно файла glibc-2.11/sysdeps/ia64/elf/start.S
/*
* Arguments for __libc_start_main:
* out0: main
* out1: argc
* out2: argv
* out3: init
* out4: fini //функция вызываемая после main
* out5: rtld_fini
* out6: stack_end
*/
Т.е. чтобы получить адрес указателя fini нужно сместиться на два машинных слова от последней локальной переменной main.
Вот что получилось(работоспособность зависит от версии компилятора):
Надеюсь, было интересно.
Удач.
Спасибо пользователю Xeor за полезную наводку.
аргументы Main-Function-и-Command-Line-«> main функции и аргументов командной строки
main Функция не имеет объявления, так как она встроена в язык. Если это так, синтаксис объявления для main будет выглядеть следующим образом:
Стандартные аргументы командной строки
Аргументы для main обеспечения удобного анализа аргументов в командной строке. Типы для параметров argc и argv определяются языком. Имена argc и argv являются традиционными, но их можно называть по своему усмотрению.
Используются следующие определения аргументов.
Сведения о подавлении обработки в командной строке см. в разделе Настройка обработки командной строки C++.
Расширения, относящиеся к Microsoft
В следующих разделах описывается поведение, характерное для Майкрософт.
Как расширение Майкрософт, main w main функции и могут быть объявлены как возвращаемые void (без возвращаемого значения). Это расширение также доступно в некоторых других компиляторах, но его использование не рекомендуется. Он доступен для симметрии, если main не возвращает значение.
main w main Сигнатуры или позволяют дополнительному расширению для доступа к переменным среды, относящимся к Microsoft. это расширение также распространено в других компиляторах для Windows и UNIX систем. Имя envp является традиционным, но вы можете присвоить параметру среды любое имя. Ниже приведены эффективные объявления для списков аргументов, включающих параметр среды:
Main «>примеры аргументов main
В следующем примере показано, как использовать argc аргументы, argv и envp в следующих main случаях:
Анализ аргументов командной строки C++
Правила синтаксического анализа командной строки, используемые кодом Microsoft C/C++, специфичны для Microsoft. Код запуска среды выполнения использует эти правила при интерпретации аргументов, заданных в командной строке операционной системы:
Аргументы разделяются пробелами (пробел или табуляция).
Строка, заключенная в двойные кавычки, интерпретируется как один аргумент, который может содержать пробелы в char актерс. Строку в кавычках можно встроить в аргумент. Курсор ( ^ ) не распознается как escape- char актер или разделитель. Внутри заключенной в кавычки строки пара двойных кавычек интерпретируется как одна экранированная двойная кавычка. Если командная строка заканчивается до тех пор, пока не будет найдена закрывающая двойная кавычка, то все char прочитанные актерс будут выводиться в качестве последнего аргумента.
Символ двойной кавычки после обратной косой черты ( \» ) интерпретируется как литеральный символ двойной кавычки ( « ).
Символы обратной косой черты считаются литералами, если сразу за ними не стоит двойная кавычка.
Если двойная кавычка стоит после четного числа символов обратной косой черты, в массив argv помещается по одному символу обратной косой черты ( \ ) для каждой пары символов обратной косой черты ( \\ ), а сама двойная кавычка ( « ) интерпретируется как разделитель строк.
Пример синтаксического анализа аргументов командной строки
В следующем примере программы показана передача аргументов командной строки:
Результаты синтаксического анализа командных строк
В следующей таблице показаны примеры входных данных и ожидаемые выходные данные, иллюстрирующие применение правил из приведенного выше списка.
Входные данные командной строки | argv [1] | argv [2] | argv 3-5 |
---|---|---|---|
«abc» d e | abc | d | e |
a\\b d»e f»g h | a\\b | de fg | h |
a\\\»b c d | a\»b | c | d |
a\\\\»b c» d e | a\\b c | d | e |
a»b»» c d | ab» c d |
Развертывание подстановочных знаков
Кроме того, компилятор Майкрософт позволяет использовать подстановочныйзнак актерс, вопросительный знак ( ? ) и звездочку ( * ), чтобы указать аргументы filename и Path в командной строке.
Дополнительные сведения о параметрах компоновщика для запуска среды выполнения см. в статье Параметры ссылок.
Настройка обработки командной строки C++
Программа может вызывать семейство подпрограмм spawn или exec в библиотеке среды выполнения C. В этом случае не следует подавлять подпрограмму обработки среды, так как она используется для передачи данных о среде из родительского процесса в дочерний.
Функция main и выполнение программ
Все программы, написанные на языке C, содержат основную функцию, которая должна иметь имя main. Если код соответствует модели программирования Юникода, можно использовать версию функции main для многобайтовых символов с именем wmain. Функция main является начальной точкой для выполнения программы. Она обычно управляет выполнением программы, вызывая другие ее функции. Как правило, выполнение программы завершается в конце функции main, но по разным причинам это может случиться и в других местах программы. Иногда (возможно, при обнаружении некоторой ошибки) может потребоваться принудительно завершить программу. Для этого используйте функцию exit. Сведения о функции exit и пример ее использования см. в Справочнике по библиотеке времени выполнения.
Синтаксис
Примечания
Функции в исходном коде программы выполняют одну или несколько конкретных задач. Функция main может вызывать эти функции для выполнения соответствующих задач. Когда функция main вызывает другую функцию, она передает ей управление выполнением, и работа программы продолжается с первого оператора вызываемой функции. Функция возвращает управление в Main при выполнении инструкции или при достижении конца функции.
Описание версии main для расширенных символов см. в статье Использование wmain.
Почему нам нужно использовать `int main`, а не` void main` в С++?
ОТВЕТЫ
Ответ 1
Как вы, вероятно, знаете, возвращаемое значение из функции main() используется библиотекой времени выполнения как код выхода для процесса. Как Unix, так и Win32 поддерживают концепцию (малого) целого числа, возвращенного из процесса после его завершения. Возврат значения из main() обеспечивает один способ для программиста указать это значение.
Ответ 2
Большинство операционных систем сообщают пользователю или процессу вызова, если приложение было успешным или нет. Это особенно полезно в сценариях, где script может условно входить (если-то) в результаты программы. Что-то вроде:
Этот статус результата выполняется с помощью возвращаемого значения main.
Хотя некоторые компиляторы разрешают void main, для согласованности и простоты стандарт ANSI требует одного прототипа main:
Поскольку в C аргументы очищаются вызывающим, автор main может пренебречь объявлением или обработкой аргументов argc и argv. Однако, если подпрограммы установки, которые вызывают main, ожидают значение int return и вместо этого не могут найти его, поведение может undefined.
Ответ 3
Основная причина изменения
в последующих выпусках было уведомить об ошибке в программе во время выполнения операционной системы, на которой она работает
идентифицировать программу успешно выполненную, если возвращаемое число, а не 0, означает, что произошла некоторая ошибка, которая возвращает код ошибки. если вы работаете с идентификатором codeblock, см. в журнале построения, если main return 0 обычно отображается
иначе он отображает код состояния красным цветом, что означает возникшую ошибку
Ответ 4
Значение, возвращаемое из основной функции, становится статусом выхода процесса, хотя стандарт C только присваивает конкретное значение двум значениям: EXIT_SUCCESS (традиционно ноль) и EXIT_FAILURE. Значение других возможных возвращаемых значений определяется реализацией.
Ответ 5
Как и в C, поскольку процесс предоставит ОС код выхода.
Вы можете использовать
Это, по крайней мере, в C89 IIRC.
Ответ 6
Вы можете запросить это значение, чтобы проверить, была ли операция успешной.
Это было очень полезно при использовании сценариев командной строки.
Ответ 7
Возможно, потому, что имеет смысл полностью выйти с кодом состояния из метода main(). В java мы должны эмулировать это, используя System.exit(), который не является настолько грациозным.
Ответ 8
Когда мы запускаем нашу программу, чтобы проверить, что она выполняется успешно или нет. Поэтому, когда он возвращает 0, это означает, что он истинно и успешно работает, если он возвращает 1, то он не запускается успешно, и это значение int сообщает операционной системе, если программа успешно завершена или нет