En los primeros días de C ++ cuando estaba atornillado encima de C, no podía usar NULL como se definió como (void*)0
. No puede asignar NULL a ningún puntero que no sea void*
, lo que lo hace un poco inútil. En aquellos días, se aceptaba que usabas 0
(cero) para punteros nulos.
Hasta el día de hoy, he seguido usando cero como puntero nulo, pero los que me rodean insisten en usarlo NULL
. Personalmente, no veo ningún beneficio en dar un nombre ( NULL
) a un valor existente, y dado que también me gusta probar los punteros como valores de verdad:
if (p && !q)
do_something();
entonces usar cero tiene más sentido (como en el caso de que lo use NULL
, no puede usarlo lógicamente p && !q
; debe compararlo explícitamente NULL
, a menos que suponga que NULL
es cero, en cuyo caso por qué usarlo NULL
).
¿Hay alguna razón objetiva para preferir cero sobre NULL (o viceversa), o todo es preferencia personal?
Editar: debería agregar (y tenía la intención de decir originalmente) que con RAII y excepciones, rara vez uso punteros cero / NULL, pero a veces todavía los necesita.
Respuestas:
Aquí está la opinión de Stroustrup sobre esto: Preguntas frecuentes sobre estilo y técnica de C ++
Dicho eso, no te preocupes por las cosas pequeñas.
fuente
Hay algunos argumentos (uno de los cuales es relativamente reciente) que creo que contradicen la posición de Bjarne sobre esto.
El uso
NULL
permite búsquedas en su uso y también destaca que el desarrollador quería usar unNULL
puntero, independientemente de si el compilador lo está interpretandoNULL
o no.El ejemplo que todos citan es:
Sin embargo, al menos en mi opinión, el problema con lo anterior no es que estemos usando NULL para la constante de puntero nulo, es que tenemos sobrecargas de 'foo' que toman muy diferentes tipos de argumentos. El parámetro también debe ser un
int
, ya que cualquier otro tipo dará como resultado una llamada ambigua y generará una advertencia útil del compilador.Incluso en ausencia de C ++ 0x, hay herramientas disponibles hoy que verifican que
NULL
se está utilizando para punteros y que0
se está utilizando para tipos integrales.std::nullptr_t
tipo.Este es el argumento más nuevo de la tabla. El problema de
0
yNULL
está siendo activamente dirigida para C ++ 0x, y se puede garantizar que por cada aplicación que proporcionaNULL
, lo primero que van a hacer es:Para aquellos que utilizan
NULL
en lugar de0
, el cambio será una mejora en la seguridad de tipos con poco o ningún esfuerzo - en todo caso también puede capturar algunos errores en que han utilizadoNULL
para0
. Para cualquiera que use0
hoy ... erm ... bueno, espero que tengan un buen conocimiento de las expresiones regulares ...fuente
#include
y manténgalo en el lado seguro por completo.#define NULL nullptr
Parece peligroso Para bien o para mal, muchos códigos heredados usan NULL para otras cosas que no sean 0. Por ejemplo, los identificadores a menudo se implementan como algún tipo integral, y su configuraciónNULL
no es infrecuente. Incluso he visto abusos como usarNULL
para establecer unchar
terminador cero.NULL
son realmente incorrectos. Muchas API se han utilizado durante mucho tiempoNULL
con identificadores, y ese es de hecho el uso documentado con muchos de ellos. No es pragmático romperlos repentinamente y declarar que lo están haciendo mal.Use NULL. NULL muestra tu intención. Que es 0 es un detalle de implementación que no debería importar.
fuente
Yo siempre uso:
NULL
para punteros'\0'
para caracteres0.0
para flotadores y doblesdonde 0 estaría bien. Es una cuestión de intención de señalización. Dicho esto, no soy anal al respecto.
fuente
Dejé de usar NULL a favor de 0 hace mucho tiempo (así como la mayoría de las otras macros). Hice esto no solo porque quería evitar las macros tanto como sea posible, sino también porque NULL parece haberse usado en exceso en el código C y C ++. Parece que se usa siempre que se necesita un valor 0, no solo para punteros.
En proyectos nuevos, pongo esto en un encabezado de proyecto:
Ahora, cuando llegan los compiladores compatibles con C ++ 0x, todo lo que tengo que hacer es eliminar esa línea. Un buen beneficio de esto es que Visual Studio ya reconoce nullptr como una palabra clave y la resalta adecuadamente.
fuente
La moraleja de la historia. Debería usar NULL cuando se trata de punteros.
1) Declara tu intención (no me hagas buscar en todo tu código tratando de averiguar si una variable es un puntero o algún tipo numérico).
2) En ciertas llamadas API que esperan argumentos variables, usarán un puntero NULL para indicar el final de la lista de argumentos. En este caso, usar un '0' en lugar de NULL puede causar problemas. En una plataforma de 64 bits, la llamada va_arg quiere un puntero de 64 bits, pero solo pasará un entero de 32 bits. ¿Me parece que estás confiando en que los otros 32 bits se pondrán a cero para ti? He visto ciertos compiladores (por ejemplo, el icpc de Intel) que no son tan amables, y esto ha resultado en errores de tiempo de ejecución.
fuente
NULL
quizás no es portátil y no es seguro. Puede haber plataformas que aún#define NULL 0
(de acuerdo con las preguntas frecuentes de Stroustrup: ¿Debería usar NULL o 0? Citado por la pregunta principal y se encuentra entre los primeros resultados de búsqueda). Al menos en C ++ anterior,0
tiene un significado conceptual especial en el contexto del puntero. No debes pensar concretamente en los bits. Tenga en cuenta también que en diferentes contextos enteros (short
,int
,long long
) "sizeof(0)
" será diferente. Creo que esta respuesta está un poco equivocada.NULL
en lugar de(char *)0
,(const char *)0
o(struct Boo *)0
o(void *)0
o lo que sea que se establece la voluntad más claramente -. Sin ser (en mi opinión) demasiado engorroso)Si recuerdo correctamente, NULL se define de manera diferente en los encabezados que he usado. Para C se define como (void *) 0, y para C ++ se define como solo 0. El código se parecía a:
Personalmente, todavía uso el valor NULL para representar punteros nulos, lo que hace explícito que estás usando un puntero en lugar de algún tipo integral. Sí internamente, el valor NULL sigue siendo 0 pero no está representado como tal.
Además, no confío en la conversión automática de enteros a valores booleanos, sino que los comparo explícitamente.
Por ejemplo, prefiero usar:
más bien que:
Baste decir que todo esto se soluciona en C ++ 11, donde uno simplemente puede usar en
nullptr
lugar deNULL
, y tambiénnullptr_t
ese es el tipo de anullptr
.fuente
Diría que la historia ha hablado y aquellos que argumentaron a favor del uso de 0 (cero) estaban equivocados (incluido Bjarne Stroustrup). Los argumentos a favor de 0 fueron principalmente estética y "preferencia personal".
Después de la creación de C ++ 11, con su nuevo tipo nullptr, algunos compiladores han comenzado a quejarse (con parámetros predeterminados) acerca de pasar 0 a funciones con argumentos de puntero, porque 0 no es un puntero.
Si el código se hubiera escrito usando NULL, una simple búsqueda y reemplazo podría haberse realizado a través de la base de código para hacerlo nullptr. Si está atascado con el código escrito usando la opción de 0 como puntero, es mucho más tedioso actualizarlo.
Y si tiene que escribir un código nuevo ahora en el estándar C ++ 03 (y no puede usar nullptr), realmente debería usar NULL. Le facilitará mucho la actualización en el futuro.
fuente
Usualmente uso 0. No me gustan las macros, y no hay garantía de que algún encabezado de terceros que estés usando no redefina NULL para que sea algo extraño.
Puede usar un objeto nullptr según lo propuesto por Scott Meyers y otros hasta que C ++ obtenga una palabra clave nullptr:
Google "nullptr" para más información.
fuente
(void*)0
si se está compilando como código C) solo está pidiendo problemas y no debe usarse.NULL
over(type *)0
es la capacidad de búsqueda, me parece a mí. De lo contrario, parece una ofuscación innecesaria si no fuera un idioma C. Personalmente, creo que el idioma de propagarseNULL
por todo el lugar merece morir.NULL
Es una macro inútil en mi opinión. La navaja de Occam tiene trabajo que hacer aquí ...Una vez trabajé en una máquina donde 0 era una dirección válida y NULL se definió como un valor octal especial. En esa máquina (0! = NULL), entonces código como
No funcionaría como esperabas. Tuviste que escribir
Aunque creo que la mayoría de los compiladores definen NULL como 0 en estos días, todavía recuerdo la lección de hace años: NULL no es necesariamente 0.
fuente
Creo que el estándar garantiza que NULL == 0, por lo que puede hacerlo. Prefiero NULL porque documenta tu intención.
fuente
foo.bar_ptr = (Bar *) 0
expresa la intención mucho más claramente quefoo.bar_ptr = NULL
. Este hábito también permite al compilador detectar errores de concepción errónea por usted. Para mí,foo.bar_ptr = 0
expresa la intención además de usarNULL
si sé quefoo.bar_ptr
es un puntero.Usar 0 o NULL tendrá el mismo efecto.
Sin embargo, eso no significa que ambas sean buenas prácticas de programación. Dado que no hay diferencia en el rendimiento, elegir una opción de bajo nivel en lugar de una alternativa agnóstica / abstracta es una mala práctica de programación. Ayude a los lectores de su código a comprender su proceso de pensamiento .
NULL, 0, 0.0, '\ 0', 0x00 y whatelse se traducen en lo mismo, pero son entidades lógicas diferentes en su programa. Deben usarse como tales. NULL es un puntero, 0 es cantidad, 0x0 es un valor cuyos bits son interesantes, etc. No asignaría '\ 0' a un puntero si se compila o no.
Sé que algunas comunidades alientan a demostrar un conocimiento profundo de un entorno al romper los contratos del entorno. Los programadores responsables, sin embargo, crean códigos mantenibles y mantienen tales prácticas fuera de su código.
fuente
Extraño, nadie, incluido Stroustroup, lo mencionó. Al hablar mucho sobre estándares y estética, nadie notó que es peligroso usarlo
0
enNULL
su lugar, por ejemplo, en una lista de argumentos variables sobre la arquitectura dondesizeof(int) != sizeof(void*)
. Al igual que Stroustroup, prefiero0
por razones estéticas, pero hay que tener cuidado de no usarlo donde su tipo pueda ser ambiguo.fuente
0
siempre y cuando se especifique lo que0
quiere decir - por ejemplo(int *)0
,(char *)0
,(const char *)0
o(void *)0
, o(unsigned long long) 0
, o lo que sea. Esto en mi opinión expresa la intención mucho más clara queNULL
.NULL
significa.(void *)
cuando podría usar el tipo exacto. A propósito di ejemplo de (típicamente) un entero de 64 bits en la lista porque es análogo al caso del puntero. Además, si recuerdo que C ++ anterior se definióNULL
como0
correcto (hace años que programé en C ++), no se observa ninguna mejora en la corrección del programa. Afortunadamente, el estándar más nuevo de C ++ proporcionanullptr
palabras clave, por lo que podemos deshacernos de estaNULL
fealdad y toda la controversia al escribir C ++ más nuevo.(void*)
se ha abstraído el castingNULL
. Y enNULL
realidad expresa la intención con bastante claridad la mayor parte del tiempo. Y creo que tu recuerdo está mal. No estoy seguro acerca de los estándares, pero en la práctica creo que lo ha sido(void*)0
. Y sí,nullptr
es un buen prettifier, aunque equivale a lo mismoNULL
: especificar un puntero nulo sin especificar el tipo.nullptr
osos tiene el mismo mensaje queNULL
, solo se trataba de expresar la intención que mencionaste al principio. (PreprocesamientoNULL
degcc
rendimientos modernos__null
, sea lo que sea).Intento evitar toda la pregunta utilizando referencias de C ++ siempre que sea posible. Más bien que
a menudo podrías escribir
Por supuesto, esto no siempre funciona; pero los punteros nulos pueden ser utilizados en exceso.
fuente
Estoy con Stroustrup en este caso :-) Como NULL no es parte del lenguaje, prefiero usar 0.
fuente
Principalmente preferencia personal, aunque uno podría argumentar que NULL hace que sea bastante obvio que el objeto es un puntero que actualmente no apunta a nada, por ejemplo
IIRC, el estándar no requiere que NULL sea 0, por lo que usar lo que esté definido en <stddef.h> es probablemente el mejor para su compilador.
Otra faceta del argumento es si debe usar comparaciones lógicas (conversión implícita a bool) o verificación de explicidad contra NULL, pero eso también se reduce a la legibilidad.
fuente
Prefiero usar NULL, ya que deja en claro que su intención es que el valor represente un puntero, no un valor aritmético. El hecho de que sea una macro es desafortunado, pero como está muy arraigado, hay poco peligro (a menos que alguien haga algo realmente descabellado). Desearía que fuera una palabra clave desde el principio, pero ¿qué puedes hacer?
Dicho esto, no tengo ningún problema con el uso de punteros como valores de verdad en sí mismos. Al igual que con NULL, es un idioma arraigado.
C ++ 09 agregará la construcción nullptr que creo que está muy atrasada.
fuente
Siempre uso 0. No por ninguna razón real, solo porque cuando estaba aprendiendo C ++ por primera vez, leí algo que me recomendó usar 0 y siempre lo hice de esa manera. En teoría, podría haber un problema de confusión en la legibilidad, pero en la práctica nunca me he encontrado con un problema de este tipo en miles de horas hombre y millones de líneas de código. Como dice Stroustrup, en realidad es solo un problema estético personal hasta que el estándar se convierte en nulo.
fuente
Alguien me dijo una vez ... Voy a redefinir NULL a 69. Desde entonces no lo uso: P
Hace que tu código sea bastante vulnerable.
Editar:
No todo en el estándar es perfecto. La macro NULL es una constante de puntero nulo C ++ definida por la implementación que no es totalmente compatible con la macro C NULL, lo que además del tipo de ocultación implícita la convierte en una herramienta inútil y propensa a errores.
NULL no se comporta como un puntero nulo sino como un literal O / OL.
Dime el siguiente ejemplo no es confuso:
Es por todo eso, en el nuevo estándar aparece std :: nullptr_t
Si no quiere esperar al nuevo estándar y quiere usar un nullptr, use al menos uno decente como el propuesto por Meyers (vea el comentario de jon.h).
fuente
NULL
es una parte bien definida del estándar C ++. Permitir que las personas a las que les gusta redefinir el código de edición de macros estándar en su proyecto haga que su código sea 'vulnerable'; usandoNULL
no lo hace.Bueno, defiendo no utilizar punteros 0 o NULL siempre que sea posible.
Usarlos tarde o temprano conducirá a fallas de segmentación en su código. En mi experiencia esto, y los punteros en gereral es una de las mayores fuentes de errores en C ++
Además, conduce a declaraciones "if-not-null" en todo el código. Mucho mejor si puede confiar siempre en un estado válido.
Casi siempre hay una mejor alternativa.
fuente
0
) es útil para la depuración. Mucho mejor que desreferenciar basura aleatoria y saber quién sabe qué resultado.Establecer un puntero a 0 simplemente no está tan claro. Especialmente si vienes un lenguaje que no sea C ++. Esto incluye C y Javascript.
Recientemente delté con un código como este:
virtual void DrawTo(BITMAP *buffer) =0;
para la función virtual pura por primera vez. Pensé que sería un jiberjash mágico durante una semana. Cuando me di cuenta de que básicamente estaba configurando el puntero de función en a
null
(ya que las funciones virtuales son solo punteros de función en la mayoría de los casos para C ++) me di una patada.virtual void DrawTo(BITMAP *buffer) =null;
Hubiera sido menos confuso que esa basterdación sin un espacio adecuado para mis nuevos ojos. En realidad, me pregunto por qué C ++ no emplea minúsculas de la
null
misma manera que emplea minúsculas falso y verdadero ahora.fuente