что такое int main в c

Несколько подробностей о функции 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
0x7ffffffff0f8NULLvoid*80x00′
2.filename[0]char1+«/tmp/a.out»
char10x00
.
env[1][0]char10x00
.
char10x00
3.0x7fffffffe5e0env[0][0]char1..
char10x00
.
argv[1][0]char10x00
.
char10x00
4.0x7fffffffe5beargv[0][0]char1+«/tmp/a.out»
5.Массив случайной длины
6.данные для auxvvoid*[]48′
AT_NULLElf64_auxv_t16
.
auxv[1]Elf64_auxv_t16
7.auxv[0]Elf64_auxv_t16Ex.:
NULLvoid*80x00
.
env[1]char*8
8.0x7fffffffe308env[0]char*80x7fffffffe5e0
NULLvoid*80x00
.
argv[1]char*8
9.0x7fffffffe2f8argv[0]char*80x7fffffffe5be
10.0x7fffffffe2f0argclong int8′число аргументов + 1
11.Локальные переменные и аргументы, функций вызываемых до main
12.Локальные переменные main
13.0x7fffffffe1fcargcint4число аргументов + 1
0x7fffffffe1f0argvchar**80x7fffffffe2f8
0x7fffffffe1e8envchar**80x7fffffffe308
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 за полезную наводку.

Источник

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.

что такое int main в c. 02 02 02 07 04 07 01. что такое int main в c фото. что такое int main в c-02 02 02 07 04 07 01. картинка что такое int main в c. картинка 02 02 02 07 04 07 01. Однажды заинтересовался, содержимым стека функции main процесса в linux. Провел некоторые изыскания и теперь представляю вам результат.

Рисунок 1. Команда вызова свойств проекта

что такое int main в c. 02 02 02 07 04 07 02. что такое int main в c фото. что такое int main в c-02 02 02 07 04 07 02. картинка что такое int main в c. картинка 02 02 02 07 04 07 02. Однажды заинтересовался, содержимым стека функции main процесса в linux. Провел некоторые изыскания и теперь представляю вам результат.

Рисунок 2. Установка аргументов командной строки

7. Каким образом в функцию Main() передать строку, которая содержит пробелы?

Бывают случаи, когда в функцию Main() нужно передать строку как один параметр. Но эта строка может содержать пробелы. В этом случае строку нужно заключить в двойные кавычки. Все что размещается между двойными кавычками не разбивается по параметрам.

Например. Пусть в функцию Main() для приложения с именем ConsoleApp1.exe нужно передать два параметра-строки:

В этом случае, вызов ConsoleApp1.exe из другого процесса (например, из командной строки) будет следующим:

В этом случае в функцию Main() будут переданы следующие значения массива args :

Важно помнить, что метод GetCommandLineArgs() возвращает массив параметров на один больше. Первым параметром, который возвращает метод (под индексом 0) идет полное имя к текущему выполняемому файлу.

9. Определение полного имени файла выполняемой программы

Нижеследующий фрагмент кода демонстрирует вывод полного имени файла текущей программы

Источник

аргументы 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 eabcde
a\\b d»e f»g ha\\bde fgh
a\\\»b c da\»bcd
a\\\\»b c» d ea\\b cde
a»b»» c dab» c d

Развертывание подстановочных знаков

Кроме того, компилятор Майкрософт позволяет использовать подстановочныйзнак актерс, вопросительный знак ( ? ) и звездочку ( * ), чтобы указать аргументы filename и Path в командной строке.

Дополнительные сведения о параметрах компоновщика для запуска среды выполнения см. в статье Параметры ссылок.

Настройка обработки командной строки C++

Программа может вызывать семейство подпрограмм spawn или exec в библиотеке среды выполнения C. В этом случае не следует подавлять подпрограмму обработки среды, так как она используется для передачи данных о среде из родительского процесса в дочерний.

Источник

Функция main и выполнение программ

Все программы, написанные на языке C, содержат основную функцию, которая должна иметь имя main. Если код соответствует модели программирования Юникода, можно использовать версию функции main для многобайтовых символов с именем wmain. Функция main является начальной точкой для выполнения программы. Она обычно управляет выполнением программы, вызывая другие ее функции. Как правило, выполнение программы завершается в конце функции main, но по разным причинам это может случиться и в других местах программы. Иногда (возможно, при обнаружении некоторой ошибки) может потребоваться принудительно завершить программу. Для этого используйте функцию exit. Сведения о функции exit и пример ее использования см. в Справочнике по библиотеке времени выполнения.

Синтаксис

Примечания

Функции в исходном коде программы выполняют одну или несколько конкретных задач. Функция main может вызывать эти функции для выполнения соответствующих задач. Когда функция main вызывает другую функцию, она передает ей управление выполнением, и работа программы продолжается с первого оператора вызываемой функции. Функция возвращает управление в Main при выполнении инструкции или при достижении конца функции.

Описание версии main для расширенных символов см. в статье Использование wmain.

Источник

Основы языка программирования C++

Структура программы

Инструкции

Программа на С++ состоит из набора инструкций. Каждая инструкция (statement) выполняет определенное действие. В конце инструкции в языке C++ ставится точка с запятой (;). Данный знак указывает компилятору на завершение инструкции. Например:

Данная строка выводит на консоль строку «Hello world!», является инструкцией и поэтому завершается точкой с запятой.

Набор инструкций может представлять блок кода. Блок кода заключается в фигурные скобки, а инструкции помещаются между открывающей и закрывающей фигурными скобками:

В этом блоке кода две инструкции, которые выводят на консоль определенную строку.

Функция main

Функция также является блоком кода, поэтому ее тело обрамляется фигурными скобками, между которыми определяется набор инструкций.

В частности, при создании первой программы использовалась следующая функция main:

И после списка параметров идет блок кода, который и содержит в виде инструкций собственно те действия, выполняемые функцией main.

Директивы препроцессора

Комментарии

Исходный код может содержать комментарии. Комментарии позволяют понять смыл программы, что делают те или иные ее части. При компиляции комментарии игнорируются и не оказывают никакого влияние на работу приложения и на его размер.

В языке C++ есть два типа комментариев: однострочный и многострочный. Однострочный комментарий размещается на одной строке после двойного слеша //:

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *