Devo retornar EXIT_SUCCESS ou 0 de main ()?

124

É uma pergunta simples, mas continuo vendo respostas conflitantes: a rotina principal de um programa C ++ deve retornar 0ou EXIT_SUCCESS?

#include <cstdlib>
int main(){return EXIT_SUCCESS;}

ou

int main(){return 0;}

Eles são exatamente a mesma coisa? EXIT_SUCCESSSó deve ser usado com exit()?

Eu pensei EXIT_SUCCESSque seria uma opção melhor, porque outro software pode querer considerar zero como falha, mas também ouvi dizer que, se você retornar 0, o compilador poderá alterá-lo para um valor diferente de qualquer maneira.

Trevor Hickey
fonte
Isso responde sua pergunta? stackoverflow.com/questions/1188335/…
Blastfurnace
2
Esta resposta sobre C90 parafraseia o padrão - 0e EXIT_SUCCESSé interpretada como um sucesso.
ta.speot.is
Responderei aqui, pois sinto que mais alguém lerá isso no futuro. Basicamente, existem muitos paradigmas sobre a aparência de "C correto". Alguns paradigmas preferem usar literais sobre macros, por exemplo, em vez de passar NULL como argumento, eles podem passar (const char *) 0 para indicar que não é apenas um nulo, mas se não for nulo, deve ser um ponteiro de caractere constante. Outros paradigmas preferem ser independentes de tipo e, ao usar tipos de macro, eles podem evitar a necessidade de alterar sua base de código quando as coisas mudam radicalmente. Por exemplo, muitos - #
Dmitry
As definições de tipo de API do Windows @Dmitry <continued> não estão corretas nas plataformas mais novas, mas, como eram macros, eles tinham uma maneira fácil de alterar todos os tipos para aqueles que funcionam redefinindo a macro, e muitos desses tipos simplesmente são dimensionados por definição (por exemplo, int é diferente em plataformas diferentes). Para resumir, use coisas como EXIT_SUCCESS se o código de retorno importa e pode mudar no futuro; caso contrário, retornar 0 pode parecer um número mágico, mas ainda é uma convenção padrão perfeitamente válida. código de erro é principalmente para programas aos resultados número de tubos de um para outro, -
Dmitry
@Dmitry <continued> usando códigos de erro para depurar seu programa é meio fraco, pois, se retornar 0, é uma informação bastante inútil, exceto em alguns casos quando houver erros não manipulados não lançados em um programa que pode fazer com que o programa seja interrompido silenciosamente, e você precisa para verificar se ele retornou normalmente (0) ou se ocorreu um erro silencioso. O retorno numérico é mais útil para canalizar 0..255 de um programa para outro com base em suas entradas; caso contrário, não há razão para pensar nisso: retorne 0 ou use um main pré-compilado que inclua uma chamada "init" nula para não visualmente incomodá-lo com retorno inútil.
Dmitry

Respostas:

150

EXIT_FAILURE, em uma declaração de retorno mainou como argumento para exit(), é a única maneira portátil de indicar falha em um programa C ou C ++. exit(1)pode realmente sinalizar o término bem-sucedido no VMS, por exemplo.

Se você estiver usando EXIT_FAILUREquando seu programa falhar, poderá usá- EXIT_SUCCESSlo quando for bem-sucedido, apenas por uma questão de simetria.

Por outro lado, se o programa nunca sinalizar falha, você pode usar 0ou EXIT_SUCCESS. Ambos são garantidos pelo padrão para sinalizar uma conclusão bem-sucedida. (É pouco possível que EXIT_SUCCESSpossa ter um valor diferente de 0, mas é igual a 0 em todas as implementações que já ouvi falar.)

Usar 0tem a menor vantagem de que você não precisa #include <stdlib.h>em C ou #include <cstdlib>em C ++ (se estiver usando uma returninstrução em vez de chamar exit()) - mas para um programa de qualquer tamanho significativo, você incluirá stdlib direta ou indiretamente de qualquer forma.

Para essa matéria, em C começando com o padrão 1999 e, em todas as versões do C ++, chegando ao fim de main()faz um implícita return 0;qualquer maneira, então você pode não precisar usar tanto 0ou EXIT_SUCCESSexplicitamente. (Mas pelo menos em C, considero explícito um return 0;estilo melhor.)

(Alguém perguntou sobre o OpenVMS. Eu não o uso há muito tempo, mas, como eu me lembro, valores de status ímpares geralmente indicam sucesso, enquanto valores pares denotam falha. A implementação C é mapeada 0para 1, de modo que return 0;indica término bem-sucedido. Outros valores são passados ​​inalterados , return 1;também indica encerramento com êxito. EXIT_FAILUREteria um valor par diferente de zero.)

Keith Thompson
fonte
@KeithThompson, você poderia esclarecer sua resposta com relação ao VMS (OpenVMS?). Não está clara a relação EXIT_SUCCESS / EXIT_FAILURE com 0 e 1. Em vez disso, explicaria os valores pares / ímpares.
malat 6/12/16
@malat: Você realmente usa o VMS?
Keith Thompson
não, nunca usei. Eu estava procurando uma resposta canônica, já que a wikipedia usava uma redação diferente .
malat 6/12/16
1
@Rhymoid: Isso é especificado por C, não por POSIX.
Keith Thompson
1
@ DeanP: 0e EXIT_SUCCESSnão é garantido que tenham o mesmo valor (mencionei isso na minha resposta), mas ambos denotam rescisão bem-sucedida. EXIT_SUCCESSé estilisticamente melhor se você também estiver usando EXIT_FAILURE, mas exit(0)tudo bem.
Keith Thompson
25

Isso não importa. Ambos são iguais.

Citações padrão C ++:

Se o valor do status for zero ou EXIT_SUCCESS, será retornado um formulário definido pela implementação do encerramento bem-sucedido do status.

Alok Save
fonte
12
Isso não importa para o compilador, mas pode ser uma questão de estilo.
Celtschk
2
@celtschk: A questão do estilo é baseada na percepção, também conhecida como Não Padronizada, para que não conte como diferença. Você só pode comparar Maçãs com Maçãs e não Maçãs com Peras.
usar o seguinte código
3
Não há garantia disso EXIT_SUCCESS == 0. Por outro lado, não há uma boa razão para isso não acontecer.
Keith Thompson
@ KeithThompson: por que Não há garantia de que EXIT_SUCCESS == 0.? Por favor, explique-o mais claramente.
Destructor
2
@PravasiMeet: um sistema pode ter mais de um valor que indica sucesso.
Keith Thompson
11

0 é, por definição, um número mágico. EXIT_SUCCESS é quase universalmente igual a 0, felizmente. Então, por que não apenas retornar / sair 0?

exit (EXIT_SUCCESS); é abundantemente claro em significado.

saída (0); por outro lado, é contra-intuitivo em alguns aspectos. Alguém não familiarizado com o comportamento do shell pode assumir que 0 == false == é ruim, assim como todos os outros usos de 0 em C. Mas não - nesse caso especial, 0 == success == good. Para os desenvolvedores mais experientes, não será um problema. Mas por que viajar com o novo cara sem absolutamente nenhuma razão?

tl; dr - se existe uma constante definida para o seu número mágico, quase nunca existe uma razão para não usar a constante em primeiro lugar. É mais pesquisável, geralmente mais claro etc. e não custa nada.

James
fonte
Acho que seus comentários sobre pessoas que esperam que 0 seja automaticamente ruim estão errados. Muitas APIs usam 0 para êxito e não 0 para falha, mesmo no stdlib. Por exemplo stdlib ( fclose(), setvbuf(), ...), POSIX ( listen(), pthread_create(), pipe(), ...), e muitos, muitos outros (por exemplo, bibliotecas OpenGL [ glGetError()], zlib [ deflate()/ inflate()/ ...], SDL [ SDL_CreateWindowAndRenderer()/ ...], e Mais).
Tim Čas
2
Claro, existem outros casos em que 0 é usado para 'sucesso', mas ele está certo quanto a ser confuso.
Paul Wintz 26/03
10

Esta é uma história sem fim que reflete os limites (um mito) da "interoperabilidade e portabilidade acima de tudo".

O que o programa deve retornar para indicar "sucesso" deve ser definido por quem está recebendo o valor (o sistema operacional ou o processo que invocou o programa) e não por uma especificação de idioma.

Mas os programadores gostam de escrever código de "maneira portátil" e, portanto, inventam seu próprio modelo para o conceito de "sistema operacional" que define valores simbólicos a serem retornados.

Agora, em um cenário de muitos para muitos (onde muitos idiomas servem para gravar programas em muitos sistemas), a correspondência entre a convenção de idiomas para "sucesso" e a convenção do sistema operacional (que ninguém pode conceder para ser sempre a mesma) deve ser tratado pela implementação específica de uma biblioteca para uma plataforma de destino específica.

Mas - infelizmente - esses conceitos não estavam tão claros no momento em que a linguagem C foi implantada (principalmente para escrever o kernel do UNIX), e os gigagramas de livros foram escritos dizendo "retorno 0 significa sucesso", pois isso era verdade no sistema operacional em naquele tempo tendo um compilador C.

A partir de então, nenhuma padronização clara foi feita sobre como essa correspondência deve ser tratada. C e C ++ têm sua própria definição de "valores de retorno", mas ninguém concede uma tradução adequada do sistema operacional (ou melhor: nenhuma documentação do compilador diz nada sobre isso). 0 significa sucesso se verdadeiro para UNIX - LINUX e - por razões independentes - também para Windows, e isso cobre 90% dos "computadores consumidores" existentes, que - na maioria dos casos - desconsideram o valor de retorno (para que possamos discutir por décadas, mas ninguém nunca notará!)

Nesse cenário, antes de tomar uma decisão, faça as seguintes perguntas: - Estou interessado em comunicar algo ao meu interlocutor sobre minha existência? (Se eu sempre retornar 0 ... não há nenhuma pista por trás de tudo) - Meu interlocutor está tendo convenções sobre essa comunicação? (Observe que um único valor não é uma convenção: isso não permite nenhuma representação de informações)

Se ambas as respostas não forem, provavelmente a boa solução é não escrever a declaração principal de retorno. (E deixe o compilador decidir, em relação ao destino que está trabalhando).

Se nenhuma convenção estiver em vigor 0 = sucesso, atenda à maioria das situações (e o uso de símbolos pode ser problemático, se introduzir uma convenção).

Se houver convenções, assegure-se de usar constantes simbólicas que sejam coerentes com elas (e garanta a coerência da convenção, e não a coerência de valor, entre plataformas).

Emilio Garavaglia
fonte
4

Depois de começar a escrever o código que pode retornar uma infinidade de status de saída, você começa #definetodos eles. Nesse caso, EXIT_SUCCESSfaz sentido no contexto de não ser um " número mágico ". Isso torna seu código mais legível, pois todos os outros códigos de saída serão EXIT_SOMETHING. Se você simplesmente escrever um programa que retornará quando terminar, return 0é válido e provavelmente ainda mais limpo, porque sugere que não há uma estrutura sofisticada de código de retorno.

Phonon
fonte
0

O que você retorna de um programa é apenas uma convenção.

Não, não consigo pensar em nenhuma circunstância em que "EXIT_SUCCESS" não seja "0".

Pessoalmente, eu recomendaria "0".

NA MINHA HUMILDE OPINIÃO...

paulsm4
fonte
1
Venho programando C ++ há 10 anos e ainda não consigo me lembrar se 0 significa sucesso ou falha em termos de valores de retorno.
lahjaton_j
@lahjaton_j Eu entendo. Acha que é porque é contra-intuitivo: 0é falso e muitas funções retornam 0em caso de falha / sem fazer nada.
significado-importa
-5

Alguns compiladores podem criar problemas com isso - em um compilador Mac C ++, EXIT_SUCCESS funcionou bem para mim, mas em um complemento Linux C ++, tive que adicionar cstdlib para saber o que é EXIT_SUCCESS. Fora isso, eles são o mesmo.

Ambidestro
fonte
Eu quis dizer em um Mac EXIT_SUCCESS funcionou sem incluir o cstdlib.
Ambidestro
4
Se EXIT_SUCCESStrabalhado sem incluir um <stdlib.h>ou <cstdlib>, algum outro cabeçalho deve ter definido, direta ou indiretamente. Em C ++, é comum para cabeçalhos padrão para #includeoutros cabeçalhos padrão. Se isso compilar sem erro: int main() { return EXIT_SUCCESS; }provavelmente o seu compilador está com erros.
Keith Thompson