如果main为void,D如何在成功时返回0,在失败时返回非零?

如果main为void,D如何在成功时返回0,在失败时返回非零?,d,D,在D中,定义了main函数: void main(/*perhaps some args but I do not remember*/) { } 我确信这个函数在成功时返回零,在失败时返回非零,但它被定义为不返回任何东西。它背后的逻辑是什么?如果将函数定义为 int main(...); void main(...); 然后返回值,您可以使用 将是从函数返回的任何内容。如果不返回任何内容,或者将main函数定义为 int main(...); void main(...); 那

在D中,定义了
main
函数:

void main(/*perhaps some args but I do not remember*/)
{

}  

我确信这个函数在成功时返回零,在失败时返回非零,但它被定义为不返回任何东西。它背后的逻辑是什么?

如果将函数定义为

int main(...);
void main(...);
然后返回值,您可以使用

将是从函数返回的任何内容。如果不返回任何内容,或者将
main
函数定义为

int main(...);
void main(...);

那么命令的退出状态是未定义的。出于某种原因(我找不到任何关于此的文档),我的系统上始终有200个签名。

对于
main()
,有几种可能的签名:

如果int是返回类型,那么它在C或C++中几乎是相同的。返回的值是OS/shell看到的值。如果抛出异常,则会打印堆栈跟踪,并且OS/shell会看到一个非零值。我不知道是什么。它可能因异常类型而异

如果void是返回类型,那么OS/shell将看到0。如果抛出异常,则打印堆栈跟踪,操作系统将看到一个非零值。再说一次,我不知道那是什么

本质上,使用voidmain可以让您不必担心向OS/shell返回值。许多程序根本不关心将成功或失败返回到OS/shell。因此,对于void,除非抛出异常,否则OS/shell总是得到0,这是有意义的,因为此时唯一的程序失败是异常逃逸
main()
。如果您确实关心将成功或失败返回到OS/shell,那么您只需使用返回int的其中一个版本


由于不同的字符串类型,签名过多,因此您几乎可以使用任何可能的字符串类型作为
main()
的输入
main()
main(string[]args)
可能是最常用的方法。

具有void返回类型的函数不返回任何值。当你认为调用堆栈看起来是这样的时候,没有什么不合逻辑的:

OS -> D runtime -> main

主函数由D运行时系统调用,该系统识别主函数不返回任何内容,在本例中,将成功返回给操作系统。如果main函数是使用返回类型int定义的,那么D运行时将返回main函数返回的OS值

Alexandrescu所说的只是我描述的退出代码的简写。返回到操作系统的零或非零是(语言无关的)进程退出代码,而不是函数返回值。操作系统不会直接调用
main
,也不会直接返回操作系统。D编译器在您的程序中插入启动和关闭代码,以处理与操作系统的这些交互,就像其他语言的编译器一样。例如,在启动时,这个样板代码使用一些依赖于操作系统的机制来获取命令行参数,并将它们放入一个D
string[]
数组中,以传递给
main
。关闭时,它使用来自
int main
的返回值作为退出代码,或者对于
void main
,使用自己的值(0表示成功,非零表示未处理的异常)

在伪代码中:

// Generated by compiler
void _realMain()
{
    // OS-dependent; probably calls GetCommandLineW
    // and CommandLineToArgvW on Windows, for example
    string[] cmdLineArgs = createArgArray();

    int exitCode = 0;    // Assume success
    try
    {
        // static if selects only one call to main for compilation,
        // depending on main's return type.

        // If main has been written to return int, use its value for the exit code
        static if (main returns int)
            exitCode = main(cmdLineArgs);
        // If main has been declared void, just run it and keep the exit code of 0
        else
            // void main: *doesn't return anything*
            main(cmdLineArgs);
    }
    catch
    {
        // Unhandled exception results in non-zero exit code
        exitCode = 1;
        printStackTrace();
    }

    // OS-dependent process shutdown function.
    // This is where the exit code is "returned" to the OS.
    // Note it *does not* use the return keyword to do so.
    // Calling the OS's function to kill the current process
    // does not return, because the process is dead by the
    // time the function has finished!
    exitProcess(exitCode);
    // In particular, no code *after* the exitProcess line will run.
}

@Delan,但如果函数定义为void作为返回类型,则它不应返回任何内容,甚至不应返回200。我的问题是,尽管void是一种返回类型,但这个函数总是返回一些东西,而且对我来说是不合逻辑的,你同意吗?如果使用
void main
,这个函数不会返回任何东西。一旦
main
返回,D运行时支持将向操作系统提供进程退出代码,而不管您使用哪种形式。如果使用
intmain
,则返回的值是传递回操作系统的值。操作系统不知道或不关心你使用什么语言;退出代码的存在并不依赖于此。@shambulator不同意,Andrei Alexandrescu说:“在D中,void main()在正常返回时向操作系统返回零(成功),在异常时向操作系统返回非零。”这对我来说是非常不合逻辑的,你同意我的观点吗?@there。。。这有什么不合逻辑的?零是成功(void意味着如果没有抛出异常,它总是成功的),而异常显然是失败的,所以这将是非零的。这似乎完全合乎逻辑,对我来说也是合乎逻辑的。程序必须有一个返回值。即使它的
main
void
@Michal,我还是接受了你的答案,因为这是最清晰的答案。但我认为,如果你看到main和void,如果有人说它返回了一些东西,这充其量是令人困惑的。在我看来,这并不是D部分的最佳选择。它有点误导,但并不比“
main
向操作系统返回一个值”更具误导性。这就是大多数语言的文档所说的,用相当多的术语来说:)总是有一个中间层来1)处理特定于操作系统的交互,2)执行语言语义。@shambulator但是main(在C++中)返回的值是返回给系统的值,对于我来说也是“语言的用户”实际上,其他层是什么并不重要——我清楚地指出,从最后一点开始,我控制(main)我的程序返回main返回的内容,并将void作为返回类型,但“隐式”返回某些内容,这只是一个坏主意。反正是给我的。当你说main向操作系统返回值是不正确的时候,它是不正确的,因为main是第一个点(或最后一个点),这取决于你如何看待它-你可以控制它,并且main返回的值准确地返回给系统。这有点像是说,我收到的信不是寄信人寄来的,而是邮递员寄来的,因为他是给我这封信的人(中间层)。这显然不是事实。他只是某种东西(返回)的转运体(中间层)