Po co zwracać NULL z main ()?

10

Czasami widzę kodery, które wykorzystują NULLjako wartość zwracaną main()w programach C i C ++, na przykład coś takiego:

#include <stdio.h>

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

    return NULL;
} 

Kiedy kompiluję ten `kod z gcc, pojawia się ostrzeżenie:

ostrzeżenie: return tworzy liczbę całkowitą ze wskaźnika bez rzutowania [-Wint-konwersji]

co jest uzasadnione, ponieważ makro NULLnależy rozszerzyć do, (void*) 0a wartość zwracana dla main powinna być typu int.

Kiedy tworzę krótki program w C ++:

#include <iostream>
using namespace std;

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

    return NULL;
}

I skompiluj to z g ++, dostaję równoważne ostrzeżenie:

ostrzeżenie: konwersja na typ nieinterpretacyjny „int” z NULL [-Wconversion-null]

Ale dlaczego używają NULLjako wartości zwracanej, main()gdy wyświetla ostrzeżenie? Czy to po prostu zły styl kodowania?


  • Jaki jest powód, aby użyć NULLzamiast 0wartości zwracanej main()pomimo ostrzeżenia?
  • Czy jest to zdefiniowane jako implementacja, czy jest to właściwe, czy nie, a jeśli tak, to dlaczego implementacja miałaby chcieć odzyskać wartość wskaźnika?
RobertS obsługuje Monikę Cellio
źródło
4
Powinieneś zapytać ich bezpośrednio.
juanchopanza
5
„dlaczego używają NULL jako wartości zwracanej przez main ()” - my nie. Autor tego kodu robi. Byłbym zainteresowany usłyszeniem ich próby uzasadnienia.
WhozCraig
1
@Vlad z Moskwy tak, ale musiałem sprawdzić, czy naprawdę było 0. ^^ - EXIT_FAILUREma 8, i wydaje się, że użycie 1 nie jest dobre na niepowodzenie, ponieważ czasami jest używane jako sukces w niektórych programach.
Waelmio
2
@RobertSsupportsMonicaCellio, jeśli tak naprawdę otrzymałeś odpowiedź, to trochę smutne. Po pierwsze, nie ma to sensu (miałoby to większy sens, gdyby było wszędzie niż gdziekolwiek ). Po drugie, jest to wyprzedaż. Jeśli piszesz kod, lepiej mieć dobry kompas, czy jest poprawny; nie tylko iść z tym, ponieważ wydaje się, że tak właśnie robi ... ktoś. Wygląda na to, że igła wskazuje właściwy kierunek (dlatego pytasz); nie tyle osoba, która napisała ten kod, a następnie podała tę odpowiedź, jako przyczynę.
WhozCraig
2
W c jest całkowicie poprawne zdefiniowanie NULLwskaźnika jako 0(bez rzutowania na void *). W takim przypadku wada pozostaje niezauważona i nie generuje ostrzeżenia. Nadal nie jest to, do czego NULL powinien być używany.
Ctx

Odpowiedzi:

14

co jest rozsądne

Tak.

ponieważ makro NULLzostanie rozwinięte do(void*) 0

Nie. W C ++ makro NULL nie może rozwijać się do (void*) 0[support.types.nullptr]. Może to zrobić tylko w C.

Tak czy inaczej pisanie takiego kodu jest mylące, ponieważ NULLpowinno odnosić się do stałej wskaźnika zerowego , niezależnie od tego, jak jest zaimplementowane. Używanie go zamiast intlogicznego błędu jest logiczne.

  • Jaki jest powód użycia NULLzamiast 0 jako wartości zwracanej main()pomimo ostrzeżenia?

Ignorancja. Nie ma dobrego powodu, aby to zrobić.

  • Czy jest to zdefiniowane jako implementacja, czy jest to właściwe, czy nie, a jeśli tak, to dlaczego implementacja miałaby chcieć odzyskać wartość wskaźnika?

Nie, to nigdy nie jest właściwe . To od implementacji zależy, czy kompilator na to pozwoli . Zgodny kompilator C ++ może na to pozwolić bez ostrzeżenia.

Konrad Rudolph
źródło
1
Mój zwykły atak: nie jest implementowane, czy kompilator na to pozwala; jest to specyficzne dla realizacji . W standardzie „zdefiniowane we wdrożeniu” oznacza, że ​​wdrożenie musi udokumentować, co robi.
Pete Becker
@PeteBecker Pauzowałem, pisząc go, ale i tak poszedłem naprzód (ponieważ „specyficzne dla implementacji” i podobne frazy po prostu brzmią nienaturalnie). Ale masz rację, zmienię to.
Konrad Rudolph
Wydaje mi się, że jedynym powodem „zdefiniowanej implementacji” brzmi naturalnie jest to, że ludzie są przyzwyczajeni do tego, że jest źle wykorzystywana. <g>
Pete Becker
8

Kiedy kompiluję ten `kod z gcc, pojawia się ostrzeżenie:

warning: return makes integer from pointer without a cast

Jest tak, ponieważ kompilujesz z opcjami kompilatora Lax. Użyj surowych ustawień standardowych C, -std=c11 -pedantic-errorsa otrzymasz oczekiwany błąd kompilatora w implementacjach, w których NULLrozwija się do stałej wskaźnika zerowego (void*)0. Zobacz problemy „Wskaźnik od liczby całkowitej / liczba całkowita od wskaźnika bez rzutowania” .

W implementacjach, w których NULLrozwija się 0, kod jest ściśle zgodny ze standardami, ale bardzo zły styl, nieprzenośny i co najgorsze: kompletny nonsens.

I skompiluj to z g ++, dostaję równoważne ostrzeżenie:

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

W C ++ 11 i późniejszych NULLnie należy go używać - zamiast tego należy użyć nullptr. Zwrócenie go z main () jest niezależnie od tego niepoprawne. NULLzawsze rozwija się 0w C ++, więc ściśle mówiąc, to zadziała, ale jest to bardzo zły styl, a co najgorsze: kompletna bzdura.

Czy to po prostu zły styl kodowania?

Nie tylko zły, ale nonsensowny styl kodowania bez żadnego uzasadnienia. Programista, który to napisał, był niekompetentny.

Lundin
źródło
2

Czy to po prostu zły styl kodowania?

Gorzej. Prawidłowym sposobem wskazania, że ​​program został poprawnie ukończony, jest

#include <stdlib.h>

int main (void)
{
    return EXIT_SUCCESS;
}
emacs doprowadza mnie do szału
źródło
1
To czysta pedanteria. Zgodnie ze standardem C argument 0 do exit()(lub wartość zwracana 0 z main) oznacza to samo co EXIT_SUCCESS.
mosvy
A ponieważ C99 można po prostu pominąć returnz main. Tak więc bardziej „poprawną” wersją twojego programu jest int main(void){};-)
mosvy
1

W? Niektórych / wielu / wszystkich? Implementacje C ++ NULLto makro rozwinięte do 0.

To po rozszerzeniu daje efekt return 0. Która jest prawidłową wartością zwracaną.

Czy to po prostu zły styl kodowania?

Tak.

Robert Andrzejuk
źródło