Подтвердить что ты не робот

Где основные параметры функции C/С++?

В C/С++ основная функция получает параметры типа char*.

int main(int argc, char* argv[]){
  return 0;
}

argv - это массив из char* и указывает на строки. Где находятся эти строки? Являются ли они в куче, стеке или где-то еще?

4b9b3361

Ответ 1

На самом деле это сочетание зависимости компилятора и операционной системы. main() - это функция, как и любая другая функция C, поэтому расположение двух параметров argc и argv будет соответствовать стандарту для компилятора на платформе. например для большинства компиляторов C, ориентированных на x86, они будут находиться в стеке чуть выше адреса возврата и сохраненного базового указателя (стек растет вниз, помните). В x86_64 параметры передаются в регистры, поэтому argc будет находиться в %edi, а argv будет в %rsi. Код в основной функции, сгенерированной компилятором, затем копирует их в стек, и это то, где позже ссылаются точки. Это значит, что регистры могут использоваться для вызовов функций из main.

Блок char*, на который указывает argv, и фактические последовательности символов могут быть в любом месте. Они будут запускаться в определенной операционной системе и могут быть скопированы с помощью кода pre-amble, который компоновщик генерирует в стек или где-то еще. Вам нужно будет посмотреть код для exec() и ассемблер pre-amble, сгенерированный компоновщиком, чтобы узнать.

Ответ 2

Это магия компилятора и зависящая от реализации.

Ответ 3

Здесь в стандарте C (n1256) говорится:

5.1.2.2.1 Запуск программы


2 Если они объявлены, параметры функции main должны подчиняться следующим Ограничения:

<уль > Значение argc должно быть неотрицательным. argv [argc] должен быть нулевым указателем.

Если значение argc больше нуля, элементы массива argv [0] через argv [argc-1] содержит указатели на строки, которые указаны определяемые реализацией значения среды хоста перед запуском программы. Цель состоит в том, чтобы предоставить информацию о программе, определенную до запуска программы из другого места в размещенной среде. Если хост-среда не способна снабжая строки буквами в верхнем и нижнем регистре, реализация должен гарантировать, что строки получены в нижнем регистре.

Если значение argc больше нуля, строка, на которую указывает argv [0] представляет собой имя программы; argv [0] [0] должен быть нулевым символом, если имя программы недоступно из среды хоста. Если значение argc равно больше единицы, строки, на которые указывает argv [1] через argv [argc-1] представляют программные параметры .

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

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

Ответ 4

Ответ на этот вопрос зависит от компилятора. Это означает, что он не рассматривается в стандарте C, поэтому любой может реализовать это, как ему хотелось бы. Это нормально, так как и операционные системы не имеют общепринятого стандартного способа запуска процессов и их завершения.

Представьте себе простой сценарий, почему бы и нет.

Процесс получает некоторым механизмом аргументы, написанные в командной строке. argc - это просто int, который помещается в стек с помощью функции bootstrap, которую компилятор помещает в качестве точки входа для процесса программы (часть времени выполнения). Фактические значения получаются из операционной системы и могут быть, скажем, записаны в блоке памяти кучи. Затем вектор argv строится и адрес в его первое положение также помещается в стек.

Затем вызывается функция main(), которую должен предоставить программист, и ее возвращаемое значение сохраняется для более позднего (почти промежуточного) использования. Структуры в куче освобождаются, и код выхода, полученный для основного, экспортируется в операционную систему. Процесс завершается.

Ответ 5

Эти параметры не отличаются от любых других параметров функции. Если последовательность вызова архитектуры требует, чтобы параметры проходили через стек, они находятся в стеке. Если, например, на x86-64, некоторые параметры входят в регистры, они также поступают в регистры.

Ответ 6

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

Типичная программа C (или С++) скомпилирована для того, что называется "размещенной" средой исполнения (с использованием функции main(), поскольку отправной точкой вашей программы является одно из требований к размещенной среде). Главное знать, что компилятор упорядочивает вещи так, что, когда исполняемый файл запускается операционной системой, среда выполнения компилятора получает управление изначально, а не функцию main(). Код инициализации времени выполнения выполняет любую инициализацию, включая выделение памяти для аргументов main(), затем передает управление на main().

Память для аргументов main() может быть получена из кучи, может быть выделена в стеке (возможно, с использованием техник, которые недоступны стандартным C-кодом), или может использовать статически выделенную память, хотя это меньше вероятный вариант только потому, что он менее гибкий. Стандарт требует, чтобы память, используемая для строк, на которые указывает argv, была модифицируемой и что изменения, внесенные в эту строку, сохраняются на протяжении всего жизненного цикла программы.

Просто имейте в виду, что до того, как выполнение достигнет main(), уже запущено немного кода, который настраивает среду для запуска вашей программы.

Ответ 7

Список аргументов является частью среды процесса, аналогичной (но отличной от) переменных среды.

Ответ 8

Обычно неизвестно, где они находятся.

#include <stdlib.h>
#include <string.h>

int main(int argc, char *argv[]) {
  char **foo;
  char *bar[] = {"foo", "bar"};

  (void)argv; /* avoid unused argv warning */

  foo = malloc(sizeof *foo);
  foo[0] = malloc(42);
  strcpy(foo[0], "forty two");

  /* where is foo located? stack? heap? somewhere else? */
  if (argc != 42) main(42, foo); else return 0;

  /* where is bar located? stack? heap? somewhere else? */
  if (argc != 43) main(43, bar); else return 0;
  /* except for the fact that bar elements
  ** point to unmodifiable strings
  ** this call to main is perfectably reasonable */

  return 0;
  /* please ignore memory leaks, thank you */
}

Ответ 9

В качестве pmg упоминается, когда main вызывается рекурсивно, это до вызывающего объекта, на который указывают аргументы. В основном ответ одинаков при исходном вызове main, за исключением того, что "вызывающий" является реализацией C/OS.

В системах UNIX-y строки, на которые указывает argv, указатели argv сами, а начальные переменные среды процесса почти всегда хранятся в самой верхней части стека.

Ответ 10

Пока вы можете получить доступ к фактическим параметрам, я думаю, что их фактическое местоположение вообще не имеет значения.