2013-06-02 2 views
2

Просмотрел исходный код для sudo, как указано на this site, и наткнулся на эту супер странную подпись типа (вопрос с бонусом: есть ли более C-подобный термин для «сигнатуры типа», ?) для главного:Использование нестандартной сигнатуры основного типа в C

int 
main(argc, argv, envp) 
    int argc; 
    char **argv; 
    char **envp; 
{ 

Я понимаю, что сам стиль является Oldskool K & R. то, что я действительно заинтересован в том факте, что главный принимают бонусный аргумент, char **envp. Зачем? sudo - довольно стандартный инструмент командной строки и вызывается как таковой. Как операционная система знает, что делать, когда она сталкивается с основной функцией, которая не определяется обычным (int argc, char *argv[])?

Много раз я сам был ленив и просто оставил аргументы полностью и независимо от того, какую программу я писал (самое опасное, что может случиться с C, я знаю: p)

Еще одна часть моего вопроса: какой классный материал позволяет вам это делать? У меня есть догадка, что это помогает куче со встроенным программированием, но у меня, к сожалению, было минимальное воздействие этого и не могу сказать. Я хотел бы видеть конкретные примеры

ответ

1

Это просто указатель на окружающую среду, идентичный

extern char **environ; 

Оба были доступны в UNIX начиная с версии 7 (в версии 6 не было никаких переменных среды). extern, названный environ, получил стандартизацию; третий аргумент main не сделал. Нет причин использовать 3-arg main, кроме как своего рода заявление о моде.

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

Системы с не-unix-подобным ABI, возможно, должны знать, какой вид main они звонят.

Put это в одном файле:

#include <stdio.h> 

int foo(int argc, char **argv) 
{ 
    int i; 
    for(i=0;i<argc;++i) 
    puts(argv[i]); 
    return 0; 
} 

И это в другом:

extern int foo(int argc, char **argv, char **envp); 
int main(int argc, char **argv) 
{ 
    char *foo_args[] = { "foo", "arg", "another arg" }; 
    char *foo_env[] = { "VAR=val", "VAR2=val2" }; 
    foo(3, foo_args, foo_env); 
    return 0; 
} 

Это совершенно неправильно с кросс-платформенного языка адвоката точки зрения. Мы солгали компилятору о типе foo и передавали ему больше аргументов, чем он хочет. Но в unix это работает. Дополнительный аргумент просто безвредно занимает слот в стеке, который должным образом учитывается и очищается вызывающим абонентом после возвращения функции или временно существует в регистре, где вызываемый не ожидает найти что-либо в частности, и какой вызывающий ожидает, что вызываемый клибером, чтобы он не возражал, если регистр повторно используется для другой цели в вызываемом.

Это именно то, что происходит с envp в обычной программе C с 2-arg main. И что происходит с argc и argv в программе с int main(void).

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

+0

Если бы вы упомянули сборку, я зацепил бы меня. Мне нравится материал низкого уровня :) Также пришлось принять за то, что заставил меня вспомнить это странное ключевое слово extern. С нетерпением ждем возможности получить руки и на самом деле обманывать это сегодня вечером, должно быть информативным – TheIronKnuckle

1

http://en.wikipedia.org/wiki/Main_function

С самого первого пункта:

Другие платформы-зависимые форматы также допускается стандартами C и C++, за исключением того, что в C++ тип возврата должен всегда быть int; [3], например, Unix (хотя и не POSIX.1) и Microsoft Windows имеют третий аргумент, дающий среду программы, в противном случае доступный через getenv в stdlib.h:

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

Смежные вопросы