Por que retornar NULL de main ()?

10

Às vezes, vejo codificadores que usam NULLcomo valor de retorno main()nos programas C e C ++, por exemplo, algo assim:

#include <stdio.h>

int main()
{
    printf("HelloWorld!");

    return NULL;
} 

Ao compilar esse código com o gcc, recebo o aviso de:

aviso: return torna inteiro do ponteiro sem conversão [-Wint-conversion]

o que é razoável porque a macro NULLdeve ser expandida (void*) 0e o valor de retorno de main deve ser do tipo int.

Quando eu faço um pequeno programa C ++ de:

#include <iostream>
using namespace std;

int main()
{
    cout << "HelloWorld!";

    return NULL;
}

E compilá-lo com g ++, recebo um aviso equivalente:

aviso: convertendo para o tipo não-ponteiro 'int' de NULL [-Wconversion-null]

Mas por que eles usam NULLcomo valor de retorno main()quando lança um aviso? É apenas um estilo de codificação ruim?


  • Qual é o motivo para usar em NULLvez de 0como valor de retorno, main()apesar do aviso?
  • É definido pela implementação se isso é apropriado ou não e, em caso afirmativo, por que alguma implementação desejaria obter um valor de ponteiro de volta?
RobertS suporta Monica Cellio
fonte
4
Você deve perguntar diretamente a eles.
juanchopanza 31/01
5
"por que eles usam NULL como valor de retorno de main ()" - nós não. O autor desse código faz. Eu estaria interessado em ouvir a tentativa deles de justificar o porquê.
WhozCraig 31/01
11
@ Vlad de Moscou sim, mas eu tive que verificar se era realmente 0 ^ ^ - EXIT_FAILUREé 8, e parece que usar 1 não é bom para uma falha, já que às vezes é usado como sucesso em alguns programas.
Waelmio 31/01
2
@RobertSsupportsMonicaCellio, se essa foi realmente a resposta que você recebeu, isso é meio triste. Primeiro, não faz sentido (faria mais sentido se estivesse em todo lugar e não em qualquer lugar ). Segundo, é um sell out. Se você estiver escrevendo um código, é melhor ter uma boa bússola para saber se está correto; não basta seguir em frente, porque é assim que parece ser feito por ... alguém. Você parece ter essa agulha apontando na direção certa (por isso está perguntando); não tanto a pessoa que escreveu esse código, que lhe deu a resposta como o motivo.
WhozCraig 31/01
2
Em c, é perfeitamente válido definir o NULLponteiro como 0(sem uma conversão para void *). Nesse caso, a falha passa despercebida e não gera um aviso. Ainda não é para isso que NULL deve ser usado.
Ctx 31/01

Respostas:

14

o que é razoável

Sim.

porque a macro NULLdeve ser expandida para(void*) 0

Não. No C ++, a macro NULL não deve ser expandida para(void*) 0 [support.types.nullptr]. Só pode fazê-lo em C.

De qualquer maneira, escrever código como este é enganoso, pois NULLdeve se referir à constante de ponteiro nulo , independentemente de como ele é implementado. Usá-lo no lugar de um inté um erro lógico.

  • Qual é o motivo para usar em NULLvez de 0 como valor de retorno, main()apesar do aviso?

Ignorância. Não há uma boa razão para fazer isso.

  • É definido pela implementação se isso é apropriado ou não e, em caso afirmativo, por que alguma implementação desejaria obter um valor de ponteiro de volta?

Não, nunca é apropriado . Cabe à implementação se o compilador permite . Um compilador C ++ em conformidade pode permitir isso sem aviso.

Konrad Rudolph
fonte
11
Meu thump usual: não é definido por implementação se o compilador permite; é específico da implementação . No padrão, "definido pela implementação" significa que a implementação deve documentar o que faz.
Pete Becker
@PeteBecker Fiz uma pausa ao escrevê-lo, mas fui em frente de qualquer maneira (porque "específicas da implementação" e frases semelhantes parecem pouco naturais). Mas você está correto, eu vou mudar.
Konrad Rudolph
Parece-me que o único motivo "definido pela implementação" parece natural é que as pessoas estão acostumadas a vê-lo mal utilizado. <g>
Pete Becker
8

Ao compilar esse código com o gcc, recebo o aviso de:

warning: return makes integer from pointer without a cast

Isso ocorre porque você compila com opções de compilador lax. Use rigorosas configurações padrão C -std=c11 -pedantic-errorse você obterá o erro esperado do compilador nas implementações em que se NULLexpande para a constante de ponteiro nulo (void*)0. Consulte o tópico "Ponteiro do número inteiro / número inteiro do ponteiro sem conversão" .

Em implementações onde se NULLexpande para0 , o código é estritamente compatível com os padrões, mas com um estilo muito ruim, não portátil e, o pior de tudo: absurdo completo.

E compilá-lo com g ++, recebo um aviso equivalente:

warning: converting to non-pointer type int from NULL [-Wconversion-null]

No C ++ 11 e além, NULLnão deve ser usado - em vez disso, use nullptr. Retorná-lo de main () está incorreto, independentemente. NULLsempre se expande para 0C ++, de forma estrita que funcionará, mas é um estilo muito ruim e o pior de tudo: um absurdo completo.

É apenas um estilo de codificação ruim?

Não apenas estilo de codificação ruim, mas sem sentido, sem qualquer justificativa. O programador que escreveu foi incompetente.

Lundin
fonte
2

É apenas um estilo de codificação ruim?

Pior. A maneira correta de indicar que o programa terminou corretamente é

#include <stdlib.h>

int main (void)
{
    return EXIT_SUCCESS;
}
emacs me deixa louco
fonte
11
Isso é puro pedantismo. De acordo com o padrão C, um argumento 0 para exit()(ou um valor de retorno 0 de main) significa o mesmo que EXIT_SUCCESS.
mosvy 31/01
E desde c99, você pode simplesmente omitir o returnde main. Portanto, uma versão mais "correta" do seu programa é int main(void){};-)
mosvy
1

Em? Alguns / muitos / todos? Implementações de C ++ NULLé uma macro expandida para0 .

Isso quando expandido em efeito dá return 0. Qual é um valor de retorno válido.

É apenas um estilo de codificação ruim?

Sim.

Robert Andrzejuk
fonte