¿Por qué devolver NULL desde main ()?

10

A veces veo codificadores que usan NULLcomo valor de retorno de programas main()C y C ++, por ejemplo, algo así:

#include <stdio.h>

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

    return NULL;
} 

Cuando compilo este `código con gcc me sale la advertencia de:

advertencia: return hace entero desde el puntero sin conversión [-Wint-conversion]

lo cual es razonable porque la macro NULLse expandirá (void*) 0y el valor de retorno de main será de tipo int.

Cuando hago un breve programa en C ++ de:

#include <iostream>
using namespace std;

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

    return NULL;
}

Y compilarlo con g ++, recibo una advertencia equivalente:

advertencia: conversión al tipo 'int' sin puntero desde NULL [-Wconversion-null]

Pero, ¿por qué usan NULLcomo valor de retorno de main()cuando arroja una advertencia? ¿Es solo un mal estilo de codificación?


  • ¿Cuál es la razón para usar en NULLlugar de 0como valor de retorno a main()pesar de la advertencia?
  • ¿Está definida por la implementación si esto es apropiado o no? De ser así, ¿por qué alguna implementación querría recuperar un valor de puntero?
RobertS apoya a Monica Cellio
fuente
44
Debes preguntarles directamente.
juanchopanza
55
"por qué usan NULL como valor de retorno de main ()" - nosotros no. El autor de ese código lo hace. Me interesaría escuchar su intento de justificar por qué.
WhozCraig
1
@Vlad desde Moscú, sí, pero tuve que verificar si realmente era 0. ^^ - EXIT_FAILUREes 8, y parece que usar 1 no es bueno para un fracaso, ya que a veces se usa como un éxito en algunos programas.
Waelmio
2
@RobertSsupportsMonicaCellio si esa fue realmente la respuesta que recibió, es un poco triste. Primero, no tiene sentido (tendría más sentido si estuviera en todas partes y no en cualquier lugar ). En segundo lugar, se agota. Si está escribiendo código, será mejor que tenga una buena brújula sobre si es correcto; no solo seguirlo porque así es como parece ser hecho por ... alguien. Parece que tienes esa aguja apuntando en la dirección correcta (por eso preguntas); no tanto la persona que escribió ese código, luego le dio esa respuesta como el motivo.
WhozCraig
2
En c, es perfectamente válido definir el NULLpuntero como 0(sin una conversión a void *). En este caso, la falla pasa desapercibida y no genera una advertencia. Todavía no es para lo que debería usarse NULL.
Ctx

Respuestas:

14

lo cual es razonable

Si.

porque la macro NULLse expandirá a(void*) 0

No. En C ++, la macro NULL no debe expandirse a (void*) 0[support.types.nullptr]. Solo puede hacerlo en C.

De cualquier manera, escribir código como este es engañoso ya que NULLse supone que se refiere a la constante de puntero nulo , independientemente de cómo se implemente. Usarlo en lugar de un intes un error lógico.

  • ¿Cuál es la razón para usar en NULLlugar de 0 como valor de retorno a main()pesar de la advertencia?

Ignorancia. No hay una buena razón para hacer esto.

  • ¿Está definida por la implementación si esto es apropiado o no? De ser así, ¿por qué alguna implementación querría recuperar un valor de puntero?

No, nunca es apropiado . Depende de la implementación si el compilador lo permite . Un compilador de C ++ conforme puede permitirlo sin previo aviso.

Konrad Rudolph
fuente
1
Mi golpe habitual: no está definido por la implementación si el compilador lo permite; es específico de implementación . En el estándar, "definido por la implementación" significa que la implementación debe documentar lo que hace.
Pete Becker
@PeteBecker Hice una pausa al escribirlo, pero seguí adelante de todos modos (porque "específico de implementación" y frases similares simplemente no suenan naturales). Pero tienes razón, lo cambiaré.
Konrad Rudolph el
Me parece que la única razón por la que "definido por la implementación" suena natural es porque las personas están acostumbradas a verlo mal utilizado. <g>
Pete Becker
8

Cuando compilo este `código con gcc me sale la advertencia de:

warning: return makes integer from pointer without a cast

Esto se debe a que compila con opciones de compilador laxas. Use una configuración estándar C estricta -std=c11 -pedantic-errorsy obtendrá el error del compilador esperado, en implementaciones donde se NULLexpande a la constante de puntero nulo (void*)0. Consulte la sección "Puntero desde entero / entero desde puntero sin conversión" .

En implementaciones en las que se NULLexpande 0, el código es estrictamente hablando compatible con el estándar, pero con un estilo muy malo, no portátil y lo peor de todo: sin sentido.

Y compilarlo con g ++, recibo una advertencia equivalente:

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

En C ++ 11 y versiones posteriores, NULLno debe usarse, en su lugar, úselo nullptr. Devolverlo desde main () es incorrecto independientemente. NULLsiempre se expande a 0C ++, por lo que, estrictamente hablando, funcionará, pero es un estilo muy malo y lo peor de todo: una completa tontería.

¿Es solo un mal estilo de codificación?

No solo es malo, sino que tiene un estilo de codificación sin sentido sin ninguna justificación. El programador que lo escribió fue incompetente.

Lundin
fuente
2

¿Es solo un mal estilo de codificación?

Peor. La forma correcta de indicar que el programa terminó bien es

#include <stdlib.h>

int main (void)
{
    return EXIT_SUCCESS;
}
emacs me vuelve loco
fuente
1
Eso es pura pedantería. Según el estándar C, un argumento 0 para exit()(o un valor de retorno 0 de main) significa lo mismo que EXIT_SUCCESS.
Mosvy
Y desde c99 puedes omitir el returnde main. Entonces, una versión más "correcta" de su programa es int main(void){};-)
mosvy
1

En? Algunos / muchos / todos? Las implementaciones de C ++ NULLes una macro ampliada a 0.

Esto cuando se expande en efecto da return 0. Cuál es un valor de retorno válido.

¿Es solo un mal estilo de codificación?

Si.

Robert Andrzejuk
fuente