Зачем возвращать NULL из main ()?

10

Я иногда вижу кодеров, которые используют в NULLкачестве возвращаемого значения в программах main()на C и C ++, например что-то вроде этого:

#include <stdio.h>

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

    return NULL;
} 

Когда я компилирую этот код с помощью gcc, я получаю предупреждение:

предупреждение: возвращение делает целое число из указателя без приведения [-Wint-преобразование]

что разумно, потому что макрос NULLдолжен быть расширен до, (void*) 0а возвращаемое значение main должно иметь тип int.

Когда я делаю короткую программу на C ++:

#include <iostream>
using namespace std;

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

    return NULL;
}

И скомпилировать его с g ++, я получаю эквивалентное предупреждение:

предупреждение: преобразование в тип без указателя 'int' из NULL [-Wconversion-null]

Но почему они используют в NULLкачестве возвращаемого значения, main()когда оно выдает предупреждение? Это просто плохой стиль кодирования?


  • Какова причина для использования NULLвместо 0возвращаемого значения main()несмотря на предупреждение?
  • Определено ли это реализацией, если это уместно или нет, и если да, то почему любая реализация захочет вернуть значение указателя?
RobertS поддерживает Монику Челлио
источник
4
Вы должны спросить их напрямую.
Juanchopanza
5
«почему они используют NULL в качестве возвращаемого значения main ()» - мы не делаем. Автор этого кода делает. Мне было бы интересно услышать их попытку объяснить почему.
WhozCraig
1
@Vlad из Москвы, да, но мне пришлось проверить, действительно ли это было 0. ^^ - EXIT_FAILUREэто 8, и, похоже, использование 1 не годится для сбоя, поскольку иногда оно используется в некоторых программах как успех.
Вельмио
2
@RobertSsupportsMonicaCellio, если это действительно был ответ, который вы получили, это довольно грустно. Во-первых, это не имеет смысла (было бы больше смысла, если бы оно было везде, а не где-либо ). Во-вторых, это распродажа. Если вы пишете код, вам лучше иметь хороший компас о том, является ли он правильным; не просто пойти с этим, потому что это похоже на то, как это делает кто-то. Кажется, у вас есть стрелка, указывающая правильное направление (поэтому вы спрашиваете); не столько человек, который написал этот код, а затем дал вам этот ответ в качестве причины.
WhozCraig
2
В c совершенно правильно определить NULLуказатель как 0(без приведения к void *). В этом случае недостаток остается незамеченным и не выдает предупреждение. Это все еще не то, для чего следует использовать NULL.
Ctx

Ответы:

14

что разумно

Да.

потому что макрос NULLдолжен быть расширен до(void*) 0

Нет. В C ++ макрос NULL не должен расширяться до (void*) 0[support.types.nullptr]. Это может быть сделано только в C.

В любом случае, написание подобного кода вводит в заблуждение, поскольку NULLпредполагается, что оно ссылается на константу нулевого указателя , независимо от того, как она реализована. Использование его вместо intлогической ошибки.

  • Какова причина для использования NULLвместо 0 в качестве возвращаемого значения main()несмотря на предупреждение?

Невежество. Нет веских причин для этого.

  • Определено ли это реализацией, если это уместно или нет, и если да, то почему любая реализация захочет вернуть значение указателя?

Нет, это никогда не подходит . От реализации зависит, позволяет ли это компилятор . Соответствующий компилятор C ++ вполне может разрешить это без предупреждения.

Конрад Рудольф
источник
1
Мой обычный удар: не определяется реализацией , позволяет ли это компилятор; это зависит от реализации . В стандарте «определение реализации» означает, что реализация должна документировать, что она делает.
Пит Беккер
@PeteBecker Я сделал паузу при написании, но все равно продолжил (потому что «специфичные для реализации» и подобные фразы звучат неестественно). Но ты прав, я это поменяю.
Конрад Рудольф
Сдается мне, что единственная причина, «определяемая реализацией», звучит естественно - люди привыкли видеть, что она используется не по назначению. <g>
Пит Беккер
8

Когда я компилирую этот код с помощью gcc, я получаю предупреждение:

warning: return makes integer from pointer without a cast

Это потому, что вы компилируете с опциями компилятора lax. Используйте строгие стандартные настройки языка Си, -std=c11 -pedantic-errorsи вы получите ожидаемую ошибку компилятора в реализациях, где NULLрасширяется до константы нулевого указателя (void*)0. Смотрите «Указатель из целого числа / целое число из указателя без приведения» .

В реализациях, где происходит NULLрасширение 0, код строго соответствует стандарту, но очень плохой стиль, непереносим и хуже всего: полная ерунда.

И скомпилировать его с g ++, я получаю эквивалентное предупреждение:

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

На C ++ 11 и выше NULLне должен использоваться - вместо этого используйте nullptr. Возвращать его из main () неверно независимо. NULLвсегда расширяется до 0C ++, так что строго говоря, это будет работать, но это очень плохой стиль и, что хуже всего: полная ерунда.

Это просто плохой стиль кодирования?

Не просто плохой, но бессмысленный стиль кодирования без какого-либо обоснования. Программист, который написал это, был некомпетентен.

Лундин
источник
2

Это просто плохой стиль кодирования?

Хуже. Правильный способ указать, что программа закончилась нормально

#include <stdlib.h>

int main (void)
{
    return EXIT_SUCCESS;
}
Emacs сводит меня с ума
источник
1
Это чистая педантичность. Согласно стандарту C, аргумент 0 для exit()(или возвращаемое значение 0 из main) означает то же самое, что и EXIT_SUCCESS.
mosvy
А с c99 вы можете просто опустить returnиз main. Итак, более «правильная» версия вашей программы int main(void){};-)
mosvy
1

В «некоторые / многие / все» Реализации C ++ NULL- это макрос, расширенный до 0.

Это при расширении в силу дает return 0. Который является допустимым возвращаемым значением.

Это просто плохой стиль кодирования?

Да.

Роберт Анджейюк
источник