int main или void main?
Для операционки может быть важно, какое число вернет твоя программа в результате выполнения. Так называемый статус. Он может означать успешное завершение или код ошибки. Т.е. правильнее было бы писать int main и самому указывать return(код_возврата) в конце программы.
Значение этой функции main - код завершения твоего приложения. Наиболее правильного написания не существует, все зависит от твоих желаний. Если ты про этот код завершения ничего не знаешь и знать не желаешь - пиши void. Если же ты его решил заюзать - то тогда пиши int, и делай return <smth>;
int main (int argc, char **argv, char **envp)
если будут еще мысли по этому поводу - буду рад
int main (int argc, char **argv, char **envp)
int main (int argc, char *argv[], char *envp[])
Так правильнее! Хотя компиляццо оба варианта =)
требую сцылку на "правильность"
В моем случае нельзя, например, написАть argv++. И это правильно!
может еще const поставить
Мб... Но в С, указатель или масив... один... одно и тоже...
Ой ли? Один константный, другой нет кажись...
а кто в java в параметрах метода ставит final?
int main(int argc, const char * argv[], const char * envp[]);
типа константный массив указателей на константные строки.
по крайней мере явный системный вызов...
Кстати да.
int main(int argc, const char * argv[], const char * envp[]);
кстати, нет
int main(int argc, char * argv[], const char * envp[]);
ох уж эти йумАристы
но я просил ссылку.
int main(void)
и не париться.
Кстати выяснилось, что C++ не позволяет перегружать (overload) main, в частности он его _никогда_ не декорирует...
код завершения твоего приложения. Наиболее правильного написания не существует, все зависит от твоих желаний
Лол Независимо от твоих желаний, C runtime воспримет то что ты вернешь как int. Даже если ничего не вернуть (void main все равно, то что окажется в регистре eax к моменту выхода из функции будет результатом ее работы.
Хотя компиляццо оба варианта
Мало ли что там
компиляццоЕсли написать
int main(int x, int y, int z)
тоже скомпилится, в этих xyz даже значения какие-то будут...
А вообще я считаю надо писать
int main(...)
!
int main(argc, argv, envp)
int argc;
char * argv[];
const char * envp[];
{
return 255;
}
так что ли?..
точно не помню, студия не стоит но вроде _tmain назыется и строки юникодные
-1- A program shall contain a global function called main, which is the designated start of the program. It is implementation-defined whether a program in a freestanding environment is required to define a main function. [Note: in a freestanding environment, start-up and termination is implementation-defined; start-up contains the execution of constructors for objects of namespace scope with static storage duration; termination contains the execution of destructors for objects with static storage duration. ]
-2- An implementation shall not predefine the main function. This function shall not be overloaded. It shall have a return type of type int, but otherwise its type is implementation-defined. All implementations shall allow both of the following definitions of main:
int main { /* ... */ }
and
int main(int argc, char* argv[]) { /* ... */ }
In the latter form argc shall be the number of arguments passed to the program from the environment in which the program is run. If argc is nonzero these arguments shall be supplied in argv[0] through argv[argc-1] as pointers to the initial characters of null-terminated multibyte strings (NTMBSs) (lib.multibyte.strings) and argv[0] shall be the pointer to the initial character of a NTMBS that represents the name used to invoke the program or "". The value of argc shall be nonnegative. The value of argv[argc] shall be 0. [Note: it is recommended that any further (optional) parameters be added after argv. ]
-3- The function main shall not be used (basic.def.odr) within a program. The linkage (basic.link) of main is implementation-defined. A program that declares main to be inline or static is ill-formed. The name main is not otherwise reserved. [Example: member functions, classes, and enumerations can be called main, as can entities in other namespaces. ]
5.1.2.2.1 Program startup
1 The function called at program startup is named main. The implementation declares no prototype for this function. It shall be defined with a return type of int and with no parameters:
int main(void) { /* ... */ }
or with two parameters (referred to here as argc and argv, though any names may be used, as they are local to the function in which they are declared):
int main(int argc, char *argv[]) { /* ... */ }
or equivalent;9) or in some other implementation-defined manner.
2 If they are declared, the parameters to the main function shall obey the following constraints:
— The value of argc shall be nonnegative.
— argv[argc] shall be a null pointer.
— If the value of argc is greater than zero, the array members argv[0] through argv[argc-1] inclusive shall contain pointers to strings, which are given implementation-defined values by the host environment prior to program startup. The intent is to supply to the program information determined prior to program startup from elsewhere in the hosted environment. If the host environment is not capable of supplying strings with letters in both uppercase and lowercase, the implementation shall ensure that the strings are received in lowercase.
— If the value of argc is greater than zero, the string pointed to by argv[0] represents the program name; argv[0][0] shall be the null character if the program name is not available from the host environment. If the value of argc is greater than one, the strings pointed to by argv[1] through argv[argc-1] represent the program parameters.
— The parameters argc and argv and the strings pointed to by the argv array shall be modifiable by the program, and retain their last-stored values between program startup and program termination.
Всё остальное - либо отклонения от стандарта (диалекты либо freestanding environment (например, прошивки всяких устройств)
Показать много-много программ, в которых есть например, такой код?
for (;argc>0;argc--,argv++) {
if (streq(*argv,"-nottyinit" {
ttyinit = FALSE;
} else if (streq(*argv,"-nottycopy" {
ttycopy = FALSE;
} else if (streq(*argv,"-noecho" {
echo = FALSE;
} else if (streq(*argv,"-console" {
console = TRUE;
} else if (streq(*argv,"-pty" {
pty_only = TRUE;
}
}
Кста, ИМХО следует использовать наиболее устойчивый к твоим ошибкам вариант, который держит твой компайлер. Вот.
Лол Независимо от твоих желаний, C runtime воспримет то что ты вернешь как int. Даже если ничего не вернуть (void main все равно, то что окажется в регистре eax к моменту выхода из функции будет результатом ее работы.
А вот это ты нагнал. Точно тебе говорю.
Потому что если функция объявлена как void, то единственный способ узнать это самое "возвращаемое значение" - это на асме заныкать куда-нить еах, а подобную процедуру не вполне корректно называть Получением Возвращенного Функцией Значения в парадигме языка С.
И екзит код она тоже нулевой оставит если void main. Проверять даже не хочу, потому что это очевидно.
Хотя про int main ( int x, int y, int z, int zz) сказал чистую правду. Я был крайне удивлен.
> Проверять даже не хочу, потому что это очевидно.
LOOOOOOOL!
Ты когда-нить C живьём видел, сыночек?
то есть наоборот массив указателей
вот именно поэтому можно делать argv++.
И для меня вообще неочевидно что нельзя применять argv++ при таком определении. если бы там const стояло - возможно. и то, спорно.
такие конструкции видел? :
int *const **const*x;
- на некоторых уровнях можно делать: x[][][][]++,
- а на некоторых нельзя: x[]++ (args.c(4) : error C2166: l-value specifies const object)
Так вот, во-первых возвращаемого значения. Я рискну предположить, что этот вопрос implementation specific, поэтому спор лишен смысла. Потому что gcc когда компилит с, говорит варнинг и действительно выдает хуйню, а когда на срр мне вообще еррор выдала, что мейн типа должен возвращать инт иниибет. А ms cl нормально компилит что .с что .срр (есть разница, я проверял никаких варнингов не выдает, еррорлевел стабильно 0 (для воид мейн). Вот.
Начет int * argv[]. Да, че-то я лажанул. Интересно, а чего ж это мне казалось, что массивы-параметры нельзя плюсплюсить? Наверное, я их с обычными перепутал.
Нет. Вопрос смысла не лишён.
Предположим есть явное объявление
extern int f ;
и подключается явно по месту реализации и по месту использования.
Тогда компилятор будет ругаться на несоответствия типов (потому что он их знает).
Если же общего объявления нет, то прототипы могут отличаться, а при линковке имена совпадут.
В случае, когда используем для вызова прототип "extern int f;", а реализовываем "void f {}",
то вызывающая функция ожидает получить результат и знает, откуда его брать,
в то время как вызываемая даже не догадывается об этом.
Теперь про main.
Внутри рантайма есть некоторый прототип (для glibc я его уже написал
которому должна соответствовать функция main.
Мы можем написать вместо него какой нибудь эквивалентный (например, с [] вместо **
или более жёсткий (const или можем не использовать часть аргументов (конвенция сишных
вызовов такое позволяет, так как стек чистится вызывающей функцией но не вернуть результат
мы не можем, так как в любом случае что-то будет воспринято как этот самый результат.
Пример:
Позле вызова f в регистре, используемом для возврата int, остаётся значение 3.
[cluster shurick]$ cat 1.c
int f{
return 3;
}
void main {
f;
}
[cluster shurick]$ gcc 1.c
1.c: In function `main':
1.c:5: warning: return type of `main' is not `int'
[cluster shurick]$ ./a.out ; echo $?
3
[cluster shurick]$
Это я к фразе:
общего объявления нет, то прототипы могут отличаться, а при линковке имена совпадут.
В случае, когда используем для вызова прототип "extern int f;", а реализовываем "void f {}",
Может быть твой любимый компилятор и не включает в сигнатуру возвращаемое значение, но это говорит только о странностях создателей твоего любимого компилятора =)
Или я вообще не понял, что ты там написал про линковку...
А насчет main и его параметров - это вообще темное дело. Судя по возможности int main (int x, int y, int z, int k) - они вообще не проверяются =) Интересно, если их написАть достаточно много, можно page fault получить? =)
Опять же, прога под мелкософт возвращает НОЛЬ! независимо от содержимого ах.
> Может быть твой любимый компилятор и не включает в сигнатуру возвращаемое значение,
> но это говорит только о странностях создателей твоего любимого компилятора =)
Я писал про C, а не про C++. "Любимый компилятор" тут ни при чём.
Сишные имена получаются только из имён функций например main -> _main,
плюсовые - из полного объявления.
Для плюсов подобный эффект достигается через extern "C" void f {} в реализации
и extern "C" int f; при использовании. Линковка будет по имени _f.
> А насчет main и его параметров - это вообще темное дело. Судя по возможности int main (int x, int y, int z, int k) - они вообще не проверяются =)
main - сишное имя.
> Опять же, прога под мелкософт возвращает НОЛЬ! независимо от содержимого ах.
Это слишком распространённые грабли. Поэтому разработчики gcc сделали warning
(и транслируют main, как обычную функцию а мелкософтовцы, похоже, сделали хак,
который применяется исключительно для void main (для не main, думаю, такое не сработает).
Тем не менее, всё, что я написал, остаётся в силе и будет работать везде независимо
от компилятора, так как использует только общие принципы языка си,
а использование каких-нибудь специфических особенностей компиляторов
типа нулевого результата void main непереносимо (и не соответствует стандарту).
Тем не менее за инфу о работе _конкретного_ компилятора сенкс.
я вроде не называл никаких конкретных регистров
Так вот, во-первых возвращаемого значения. Я рискну предположить, что этот вопрос implementation specific, поэтому спор лишен смысла.Можно ещё раз перечитать 5.1.2.2.1 Program startup, учитывая значение слова "shall", как его трактуют в сам'oм стандарте:
1. In this International Standard, ‘‘shall’’ is to be interpreted as a requirement on an implementation or on a program; conversely, ‘‘shall not’’ is to be interpreted as a prohibition."мой любимый компилятор" здесь не аргумент.
2 If a ‘‘shall’’ or ‘‘shall not’’ requirement that appears outside of a constraint is violated, the behavior is undefined. Undefined behavior is otherwise indicated in this International Standard by the words ‘‘undefined behavior’’ or by the omission of any explicit definition of behavior. There is no difference in emphasis among these three; they all describe ‘‘behavior that is undefined’’
У мелкософта, кстати,в описании главной функции написано, что она может быть в трёх видах -
int main
int main(int argc, char *argv[]) или char **argv
int main(int argc, char *argv[], char *argp[]) // то же самое, что и в пред. случае.
кстати, последний случай оговорен в стандарте как "Language extensions", п. J.5.1
Alternatively, the main and wmain functions can be declared as returning void (no return value). If you declare main or wmain as returning void, you cannot return an exit code to the parent process or operating system using a return statement; to return an exit code when main or wmain are declared as void, you must use the exit function.
тогда поймешь в чем здесь толк
Мы какой документ имеем в виду?
у меня такого пункта нету
Предлагаю модераторам тред закрыть
Согласен
тип возвращаемой переменной имя функции (переменные передаваемые этой функции)
И если какие-либо переменные отсутствуют, желательно писить void
То есть если программа не собирается возвращать переменную, и не принимает что-либо из командной строки, то правильно писать так:
void main(void)
void main(void)
А тебе не приходило в голову, что прототип функции при ее определении должен соответствовать ее прототипу при вызове? Согласись, если в одном файле написать
void mymalloc(void)
{
printf("Хрен вам а не malloc!\n");
}
а в другом
int * mymalloc(void);
int main(void)
{
int * p = mymalloc;
*p = 10;
}
потом скомпилировать их и слинковать вместе, то что-то будет не так?
А функция main
(а main это функция как ни странно)и она как ни странно вызывается из другой С функции, которая например в VC7 называется mainCRTStartup и в месте вызова предполагается, что main вернет int. Ты вообще тред внимательно прочитал перед тем как умничать?
сорри за ламерский вопрос, но все же.......сорри за ламерский ответ, но все же.......
1. Насколько я помню (но не твёрдо стандарт говорит о функциции int main(......)
2. Если ты напишешь void main(..... компилятору это не понравится, но он сделает вид, что ничего не заметил.
3. Лично я всю жизнь писал void main
4. В C/C++ отсутствие типа подразумевает int, так что можно писать просто main(.....)
5. В C main(void) это то же самое, что и в C++ main (функция не принимает аргументов)
6. В C main это то же самое, что и main(...) (функция принимает ЛЮБЫЕ аргументы)
Оставить комментарий
korol41
сорри за ламерский вопрос, но все же.......как правильно писать в проге на Си: int main или void main?
я встречал и тот и другой вариант, оба компилируются без проблем, но все-таки: как писать правильнее?
может быть, даже с точки зрения хорошего стиля, что ли......