Различные соглашения для main() в C
Мое единственное воздействие на программирование было Java, где я не встречал (до сих пор) разные соглашения для написания основного метода. Я следил за источниками обучения c (K & R AND C Programming A Modern Approach) где они используют самые разные формы основного метода (функции).
версия K & R до сих пор:
main() {
blah blah blah;
}
C Программирование Современный подход
int main() {
blah blah blah;
return 0;
}
ИЛИ
int main() {
blah blah blah;
//returns nothing
}
Чтобы сделать вещи более запутанными, я видел людей:
int main(void) {
blah blah blah;
}
пока они либо вернули 0, либо не сделали этого.
Я не в своем необразованном предположении думаю, что это только проблема стандартов, но, возможно, нечто более концептуальное или глубокое.
Может ли кто-то пролить свет на эту проблему?
Ответы
Ответ 1
-
K & R-стиль устарел и не соответствует правилу в соответствии со стандартом C.
-
Действительные сигнатуры
int main(void)
и
int main(int argc, char *argv[])
или, что эквивалентно, потому что тип массива в функции всегда настроен на тип указателя:
int main(int argc, char **argv)
-
Подпись
int main()
также является допустимым, поскольку пустой список аргументов означает любое количество аргументов, которые не описаны *). AFAIK, это может быть изменено, поэтому не пишите так. Написание void
заключается в том, как вы выражаете эту функцию, не принимает аргументы в C.
-
Реализации C могут предоставлять другие точки входа, определенные реализацией. Но два, перечисленных выше, являются единственными, гарантированными стандартом.
-
В C99 введено специальное правило для main()
, в котором указано, что функция ничего не возвращает, значение 0
возвращается неявно. Итак, только в основном, вы можете пропустить return
. Мой совет: не надо. Это просто сбивает с толку. Но это мнение.
*) обратите внимание, что это другое в С++, где ничто между скобками действительно не означает: никаких аргументов.
Ответ 2
Предварительно стандартизованные версии C (известные как K & R C) имели концепцию типа int
по умолчанию, если ни один не был указан. Итак, в K & R это:
main() {
То же, что и:
int main() {
Что касается разницы между int main()
и int main(void)
, пустой список параметров означает, что функция принимает неопределенное количество параметров, а (void)
в качестве списка параметров означает, что функция не принимает никаких параметров. Первое допустимо, но последнее предпочтительнее, поскольку оно более явственно.
Что касается использования оператора return
, функция с типом не-void return должна использовать return
для возврата значения, за исключением (начиная со стандартного C99) для main
. В случае main
отсутствующий оператор return
подразумевает возвращаемое значение 0.
Поскольку неявный return 0
для main был добавлен в C99, вы увидите некоторый код, который явно возвращается, и некоторые, которые не зависят от того, какая версия стандарта соответствует программисту.
Ответ 3
Существует два стандартных подписи для main
по последнему стандарту языка C:
int main( void ) // void indicates "takes no arguments"
и
int main( int argc, char *argv[] ) // or char **argv, it means the same thing in this context
Имена argc
и argv
являются произвольными; вы можете использовать разные имена, если хотите.
Реализации могут предоставлять дополнительные допустимые сигнатуры для main
- проверить вашу документацию компилятора.
Если ваша программа не принимает аргументы командной строки, используйте первую форму, в противном случае используйте вторую.
Объявление функции C и синтаксис определения со временем развивались, поэтому разные ссылки используют разные соглашения.
Неявный ввод
Прежде всего, C первоначально допускал неявные объявления int
- если компилятор видел определение или объявление функции без спецификатора типа, он предположил, что функция возвращена int
:
foo(); // modern equivalent: int foo( void )
Это было разрешено вплоть до стандарта 1999 года, хотя многие из нас считались плохого стиля задолго до этого.
Ключевое слово void
не было введено до стандарта 1989 года. В качестве спецификатора типа он указывает тип без значений. В качестве идентификатора в списке параметров функции он указывает, что функция не принимает аргументов.
До появления ключевого слова void
не было хорошего способа (кроме документации), чтобы отличать функции, возвращающие значение, которое вы должны использовать, вместо функций, которые только что выполнили какое-либо действие. Некоторые из нас использовали термин "неявный int
", чтобы указать, что эти функции не предназначены для возврата каких-либо значимых значений:
foo(); /* returns int, but return value not meant to be used */
int bar(); /* returns int, return value meant to be used */
Опять же, это была просто конвенция и далека от всеобщей. Теперь мы будем использовать ключевое слово void
:
void foo(); /* does not return a value */
int bar(); /* returns int */
Синтаксис прототипа функции
Первоначально определение функции выглядело примерно так:
foo( bar, bletch, blurga )
int bar;
double bletch;
char *blurga;
{
/* function body */
}
В списке параметров указаны только имена параметров, а не их типы; это было сделано в отдельном наборе объявлений между декларатором функции и открытием {
тела функции. Функция, которая не принимала аргументов, содержала в определении функции пустой список идентификаторов:
blah( )
{
/* function body */
}
В объявлениях функций указано только имя и тип возврата функции; он вообще не указывал параметры:
foo( ); /* no bar, bletch, or blurga */
Пустой список идентификаторов в объявлении функции указывает, что функция принимает неопределенное количество аргументов, а не нулевые аргументы. Компилятор мог проверить правильность использования возвращаемого типа вызова функции, но он не мог проверить правильность числа и типов параметров в вызове.
В стандарте 1989 года была введена концепция синтаксиса прототипа функции, где в каждом параметре был указан тип каждого параметра вместе с его именем:
foo( int bar, double bletch, char *blurga )
{
/* function body */
}
Это применимо как к объявлению функции, так и к определению:
foo( int bar, double bletch, char *blurga );
Это изменение позволило компилятору проверить правильность числа и типов параметров в вызове функции вместе с типом возврата. Кроме того, ключевое слово void
можно было бы использовать в списке параметров, чтобы указать, что функция не принимала никаких параметров в определении и декларации:
blah( void ); /* declaration, returns int, takes no parameters */
blah( void ) /* definition */
{
/* function body */
}
Итак, в зависимости от того, с какой версией языка вы работаете, main
будет написано иначе:
K & R:
main() main( argc, argv )
{ int argc;
... char *argv[];
} {
...
}
C89:
main( void ) main( int argc, char *argv[] )
{ {
... ...
} }
C99 и более поздние версии:
int main( void ) int main( int argc, char *argv[] )
{ {
... ...
} }
Ответ 4
Стандарт C определяет подпись для main
либо как
int main(void)
или
int main(int argc, char *argv[])
Добавление return 0;
в качестве последнего оператора в main
не является обязательным.
Стандарт также говорит о некотором прототипе, определенном для реализации. int main()
принимается компилятором GCC.
main()
является старым школьным прототипом и почти не рекомендуется.