Pourquoi renvoyer NULL de main ()?

10

Je vois parfois des codeurs qui utilisent NULLcomme valeur de retour main()dans les programmes C et C ++, par exemple quelque chose comme ça:

#include <stdio.h>

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

    return NULL;
} 

Quand je compile ce `code avec gcc, je reçois l'avertissement de:

avertissement: return rend entier à partir d'un pointeur sans transtypage [-Wint-conversion]

ce qui est raisonnable car la macro NULLdoit être étendue à (void*) 0et la valeur de retour de main doit être de type int.

Quand je fais un petit programme C ++ de:

#include <iostream>
using namespace std;

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

    return NULL;
}

Et compilez-le avec g ++, j'obtiens un avertissement équivalent:

avertissement: conversion en type non-pointeur 'int' de NULL [-Wconversion-null]

Mais pourquoi utilisent-ils NULLcomme valeur de retour main()quand il lance un avertissement? Est-ce juste un mauvais style de codage?


  • Quelle est la raison d'utiliser NULLau lieu de 0comme valeur de retour main()malgré l'avertissement?
  • Est-il défini par l'implémentation si cela est approprié ou non et si oui, pourquoi une implémentation voudrait-elle récupérer une valeur de pointeur?
RobertS soutient Monica Cellio
la source
4
Vous devriez leur demander directement.
juanchopanza
5
"pourquoi utilisent-ils NULL comme valeur de retour de main ()" - nous ne le faisons pas. L'auteur de ce code le fait. Je serais intéressé d'entendre leur tentative de justifier pourquoi.
WhozCraig
1
@Vlad de Moscou oui mais j'ai dû vérifier si c'était vraiment 0. ^^ - EXIT_FAILUREest 8, et il semble que l'utilisation de 1 n'est pas bonne pour un échec car elle est parfois utilisée comme succès dans certains programmes.
Waelmio
2
@RobertSsupportsMonicaCellio si c'était vraiment la réponse que vous avez reçue, c'est un peu triste. Premièrement, cela n'a pas de sens (cela aurait plus de sens s'il était partout plutôt que n'importe où ). Deuxièmement, c'est une rupture de stock. Si vous écrivez du code, vous feriez mieux d'avoir une bonne boussole pour savoir s'il est correct; pas seulement parce que c'est comme ça que ça semble être fait par ... quelqu'un. Vous semblez avoir cette aiguille pointant dans la bonne direction (c'est pourquoi vous demandez); pas tant la personne qui a écrit ce code, puis qui vous a donné cette réponse que la raison.
WhozCraig
2
En c, il est parfaitement valide de définir le NULLpointeur comme 0(sans transtypage en void *). Dans ce cas, la faille passe inaperçue et ne génère pas d'avertissement. Ce n'est toujours pas la raison pour laquelle NULL doit être utilisé.
Ctx

Réponses:

14

ce qui est raisonnable

Oui.

parce que la macro NULLdoit être étendue à(void*) 0

Non. En C ++, la macro NULL ne doit pas s'étendre à (void*) 0[support.types.nullptr]. Il ne peut le faire qu'en C.

Quoi qu'il en soit, écrire du code comme celui-ci est trompeur car il NULLest censé faire référence à la constante du pointeur nul , quelle que soit la façon dont elle est implémentée. L'utiliser à la place d'un intest une erreur logique.

  • Quelle est la raison d'utiliser NULLau lieu de 0 comme valeur de retour de main()malgré l'avertissement?

Ignorance. Il n'y a aucune bonne raison de le faire.

  • Est-il défini par l'implémentation si cela est approprié ou non et si oui, pourquoi une implémentation voudrait-elle récupérer une valeur de pointeur?

Non, ce n'est jamais approprié . C'est à l'implémentation si le compilateur le permet . Un compilateur C ++ conforme peut très bien le permettre sans avertissement.

Konrad Rudolph
la source
1
Mon coup habituel: il n'est pas défini par l'implémentation si le compilateur le permet; il est spécifique à la mise en œuvre . Dans la norme, "défini par implémentation" signifie que l'implémentation doit documenter ce qu'elle fait.
Pete Becker
@PeteBecker J'ai fait une pause lors de l'écriture, mais j'ai quand même continué (car «spécifique à l'implémentation» et des phrases similaires ne semblent pas naturelles). Mais vous avez raison, je vais le changer.
Konrad Rudolph
Il me semble que la seule raison pour laquelle «défini par la mise en œuvre» semble naturel est que les gens ont l'habitude de le voir mal utilisé. <g>
Pete Becker
8

Quand je compile ce `code avec gcc, je reçois l'avertissement de:

warning: return makes integer from pointer without a cast

C'est parce que vous compilez avec les options du compilateur lax. Utilisez des paramètres standard C stricts -std=c11 -pedantic-errorset vous obtiendrez l'erreur de compilation attendue, sur les implémentations où se NULLdéveloppe la constante de pointeur nul (void*)0. Voir «Pointeur à partir d'un entier / entier à partir d'un pointeur sans transtypage» .

Sur les implémentations où se NULLdéveloppe 0, le code est strictement conforme aux normes, mais très mauvais style, non portable et le pire de tout: un non-sens complet.

Et compilez-le avec g ++, j'obtiens un avertissement équivalent:

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

Sur C ++ 11 et au-delà, NULLne devrait pas être utilisé - utilisez plutôt nullptr. Le renvoyer de main () est incorrect malgré tout. NULLse développe toujours 0en C ++ donc à proprement parler cela fonctionnera, mais c'est un très mauvais style et le pire de tout: un non-sens complet.

Est-ce juste un mauvais style de codage?

Pas seulement mauvais, mais un style de codage absurde sans aucune justification. Le programmeur qui l'a écrit était incompétent.

Lundin
la source
2

Est-ce juste un mauvais style de codage?

Pire. La bonne façon d'indiquer que le programme s'est bien terminé est

#include <stdlib.h>

int main (void)
{
    return EXIT_SUCCESS;
}
emacs me rend dingue
la source
1
C'est de la pédanterie pure. Selon la norme C, un argument 0 à exit()(ou une valeur de retour 0 de main) signifie la même chose que EXIT_SUCCESS.
mosvy
Et depuis c99, vous pouvez simplement omettre le returnfrom main. Donc, une version plus "correcte" de votre programme est int main(void){};-)
mosvy
1

Dans? Certains / plusieurs / tous? Les implémentations C ++ NULLsont une macro étendue à 0.

Ceci une fois étendu en effet donne return 0. Ce qui est une valeur de retour valide.

Est-ce juste un mauvais style de codage?

Oui.

Robert Andrzejuk
la source