C语言 为什么我们不在 main 中使用 (void)?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3156423/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 05:47:03  来源:igfitidea点击:

Why don't we use (void) in main?

c

提问by fuddin

People use void main() /*empty parens ()*/

人们使用 void main() /*empty parens ()*/

I have been taught to write void main(void)

我被教导写作 void main(void)

Any ideas what the difference is?

任何想法有什么区别?

回答by Noldorin

I'm not sure what the standards are nowadays, but in traditional ANSI C, using empty parentheses indicates that the function can take anynumber of arguments. Declaring a voidparameter on the other hand indicates that the function only takes zero arguments. In this case (and many others), it really doesn't matter too much.

我不确定现在的标准是什么,但在传统的 ANSI C 中,使用空括号表示该函数可以采用任意数量的参数。void另一方面,声明一个参数表明该函数只接受零个参数。在这种情况下(以及许多其他情况),这真的没有太大关系。

If you want to be strict though, it's probably best to define the voidparameter. Of course, the mainfunction can also be defined as int main(int argc, const char* argv[])- which is perfectly valid, but often unnecessary if you don't care about arguments.

如果你想严格一点,最好定义void参数。当然,该main函数也可以定义为int main(int argc, const char* argv[])- 这是完全有效的,但如果您不关心参数,则通常是不必要的。

回答by Tim Schaeffer

From the C99 standard:

来自 C99 标准:

5.1.2.2.1 Program startup

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; or in some other implementation-defined manner.

5.1.2.2.1 程序启动

程序启动时调用的函数名为 main。实现声明没有此函数的原型。它应定义为返回类型为 int 且不带参数:

int main(void) { /* ... */ }

或带有两个参数(此处称为 argc 和 argv,尽管可以使用任何名称,因为它们对于声明它们的函数而言是本地的):

int main(int argc, char *argv[]) { /* ... */ }

或同等学历; 或以其他一些实现定义的方式。

When main is defined without parameters, will argc and argv still be present on the stack?

当 main 定义为不带参数时, argc 和 argv 是否仍然存在于堆栈中?

回答by Gery

These prototypes of main() are both non-standard.

main() 的这些原型都是非标准的。

Precision on that question can be found on the comp.lang.c faq : http://c-faq.com/decl/main.html

可以在 comp.lang.c 常见问题解答中找到该问题的精确性:http: //c-faq.com/decl/main.html

EDIT: changed "wrong" to "non-standard" as the norm allows implementation-defined prototypes.

编辑:将“错误”更改为“非标准”,因为规范允许实现定义的原型。

回答by INS

There is no difference but usually main should return int. Some compilers will give you a warning (at least the GNU compiler - gcc):

没有区别,但通常 main 应该返回 int。一些编译器会给你一个警告(至少是 GNU 编译器 - gcc):

$ cat x.c
void main(void){}

$ gcc x.c
x.c: In function `main':
x.c:1: warning: return type of 'main' is not `int'

As mentioned the prototype of main is (according to standard):

如前所述, main 的原型是(根据标准):

int main(int argc, const char* argv[])

int main(int argc, const char* argv[])

回答by ShinTakezou

mainis a function, as other function. Almost. Anyway, being a function, it is called by some other code (a start up code). Usually (read: almost always) int main()is the correct one, but indeed what is the real correct one depends on the platform you are working it. Since, as said, main function could be called by a startup code that pass in no arguments at all, and that expect no a return value in a specific register (so that void main(void)is correct).

main是一个函数,就像其他函数一样。几乎。无论如何,作为一个函数,它被一些其他代码(启动代码)调用。通常(阅读:几乎总是)int main()是正确的,但实际上什么是真正正确的取决于您使用的平台。因为,如上所述, main 函数可以被启动代码调用,该代码根本不传入任何参数,并且不期望特定寄存器中的返回值(所以这void main(void)是正确的)。

The int main()is correct since normally start up code expect a return value, and pass in two arguments. By saying int main(void)you are saying main takes no argument at all, that is false in most cases. With ()you say there are arguments (one, two, three, you don't care), but you are not interested in them, so you are not interested in saying what they are and which type they are.

int main()是正确的,因为通常启动代码期望返回值,并传入两个参数。通过说int main(void)您说 main 根本不需要参数,这在大多数情况下是错误的。有了()你说有争论(一,二,三,你不关心),但你是不是在他们的兴趣,所以你是不是在说它们是什么以及哪些类型,他们有兴趣。

As I can see in codes, the most used prototype for "normal" environments (no embedded device or other "strange" environments where main can be called differently) is int main()when you disregard the passed int argc, char **argvarguments. (GCC complain since we are using a version for gcc suitable for the enviroment; test it with cross GCC version for one of the environment where startup code does not pass any arguments and expect no a return value)

正如我在代码中看到的,“正常”环境(没有嵌入式设备或其他“奇怪”环境,其中 main 可以以不同方式调用)最常用的原型是int main()当您忽略传递的int argc, char **argv参数时。(GCC 抱怨,因为我们使用的是适合该环境的 gcc 版本;在其中启动代码不传递任何参数且不期望返回值的环境之一中使用跨 GCC 版本对其进行测试)

edit

编辑

Just to be kind to skeptical persons; on the an environment where the main function is called, with two arguments, the following

只是善待怀疑的人;在调用 main 函数的环境中,有两个参数,以下

int func()
{
  return 0;
}

int func2(void)
{
  return 1;
}

int main(void)
{
  int a;
  a = func(a, a); /* A */
  a = func2(a);   /* B */
  return 0;
}

says no error for A, while for B says too many arguments to function ‘func2', compiled with gcc -std=c99 -pedantic. Changing int main(void)into int main()makes no difference, and no warnings.

说 A 没有错误,而 B 说too many arguments to function ‘func2',用gcc -std=c99 -pedantic. 更改int main(void)int main()没有区别,也没有警告。

On other evironments (I can't do practical tests now), void main(void)is ok, while in this case it raises a warning. The warning is not because of standard alone, but only since in the environment in use the prototype for main does not match. Standard seems to allow any other "configuration" for main.

在其他环境中(我现在无法进行实际测试),没问题void main(void),但在这种情况下它会发出警告。警告不是因为标准本身,而是因为在使用的环境中 main 的原型不匹配。标准似乎允许主的任何其他“配置”。

In the OP case, considerering the "normal" enviroment (O.S. like GNU/Linux e.g.), where two args are passed to the main, and a return value is expected, the int main()is preferable (arguments are pushed on the stack by the startup code whether you say int main(void)or not, so int main()to me make more sense)

在 OP 情况下,考虑到“正常”环境(例如 GNU/Linux 之类的操作系统),其中两个 args 传递给 main,并且期望返回值,这int main()是更可取的(参数由启动代码推送到堆栈上)不管你说不说int main(void),所以int main()对我来说更有意义)

edit

编辑

One more note, always for skeptical person. As already proved, B raises an error, since I've said that it is int func2(void)but I call it passing an argument. Then, let us suppose we can compile the startup code and link it, as any other code. Somewhere, it will call the main, in a way like

多注意一点,总是给持怀疑态度的人。正如已经证明的那样,B 引发了一个错误,因为我已经说过它是,int func2(void)但我称之为传递参数。然后,让我们假设我们可以像任何其他代码一样编译启动代码并链接它。在某处,它会以一种方式调用 main

retval = main(argc, argv);

If we used int main(void), the compiler will stop, giving an error, since startup code (in this environment) is trying to call main with two arguments. If we use int main()nothing happens and the code gets compiled correctly.

如果我们使用int main(void),编译器将停止,给出一个错误,因为启动代码(在这种环境中)试图用两个参数调用 main。如果我们使用int main()什么都不会发生并且代码被正确编译。

So, int main()is superiorto int main(void)(in environment where we expect two arguments to main possible)

那么,int main()上级int main(void)(在环境,我们有两个参数主可能)

edit

编辑

More likely the call is like

更有可能的电话是

retval = main(_argc, _argv, environ);

on many systems, but this does not change the previous speech.

在许多系统上,但这并没有改变之前的演讲。

final edit

最终编辑

Did anyone find that when building a command line tool (i.e. on systems where int argc, char **makes sense) with int main(void), the chosen compiler/linker links a startup code where the mainis called without arguments (whatever the calling conventions are), and instead when building with int main(int argc, char **argv)the startup code is different and in fact calls the mainwith those two arguments (even if the mainitself doesn't use them)?

有没有人发现在使用 构建命令行工具(即在int argc, char **有意义的系统上)时int main(void),选择的编译器/链接器链接启动代码,在该代码中main调用 不带参数(无论调用约定是什么),而不是在使用int main(int argc, char **argv)启动构建时代码是不同的,实际上是main用这两个参数调用的(即使main它本身不使用它们)?