¿Se me permite usar el NULL
puntero como reemplazo del valor de 0
?
¿O hay algo malo en hacer eso?
Como por ejemplo:
int i = NULL;
como reemplazo de:
int i = 0;
Como experimento compilé el siguiente código:
#include <stdio.h>
int main(void)
{
int i = NULL;
printf("%d",i);
return 0;
}
Salida:
0
De hecho, me da esta advertencia, que es completamente correcta por sí sola:
warning: initialization makes integer from pointer without a cast [-Wint-conversion]
pero el resultado sigue siendo equivalente.
- ¿Estoy cruzando con "Comportamiento indefinido" con esto?
- ¿Está permitido utilizar
NULL
de esta manera? - ¿Hay algo de malo en usar
NULL
como valor numérico en expresiones aritméticas? - ¿Y cuál es el resultado y el comportamiento en C ++ para este caso?
He leído las respuestas de ¿Cuál es la diferencia entre NULL, '\ 0' y 0 sobre cuál es la diferencia entre NULL
, \0
y 0
es, pero no obtuve la información concisa de allí, si es bastante permisible y también correcto usarlo NULL
como valor para operar en asignaciones y otras operaciones aritméticas.
Respuestas:
No , no es seguro hacerlo.
NULL
es una constante de puntero nulo, que podría tener tipoint
, pero que normalmente tiene tipovoid *
(en C), o de lo contrario no se puede asignar directamente a unint
(en C ++> = 11). Ambos lenguajes permiten que los punteros se conviertan en enteros, pero no prevén que tales conversiones se realicen implícitamente (aunque algunos compiladores lo ofrecen como una extensión). Además, aunque es común convertir un puntero nulo en un entero para obtener el valor 0, el estándar no garantiza eso. Si desea una constante con tipoint
y valor 0, deletreela0
.Sí, en cualquier implementación donde se
NULL
expande a un valor con tipovoid *
o cualquier otro que no sea directamente asignableint
. El estándar no define el comportamiento de su asignación en dicha implementación, por lo tanto, su comportamiento no está definido.Es un estilo pobre, y se romperá en algunos sistemas y en algunas circunstancias. En la medida en que parezca que está utilizando GCC, se rompería en su propio ejemplo si compilara la
-Werror
opción.Si. No se garantiza que tenga un valor numérico en absoluto. Si quiere decir 0, escriba 0, que no solo está bien definido, sino que es más corto y claro.
El lenguaje C ++ es más estricto con respecto a las conversiones que C y tiene reglas diferentes para
NULL
, pero también, las implementaciones pueden proporcionar extensiones. De nuevo, si te refieres a 0, entonces eso es lo que debes escribir.fuente
void *
" solo es cierto para C.void *
no es un tipo legal para C ++ (porque no puede asignarvoid*
a ningún otro tipo de puntero). En C ++ 89 y C ++ 03, de hechoNULL
debe ser de tipoint
, pero en versiones posteriores puede ser (y generalmente lo es)nullptr_t
.void*
aint
es un comportamiento indefinido. No lo es; Es el comportamiento de implementación especificado.NULL
es un puntero nulo constante. En C podría ser una expresión constante entera con valor0
o una expresión de ese tipo convertida envoid*
, con la última más probable. Lo que significa que no puede asumir que se usaNULL
indistintamente con cero. Por ejemplo, en este ejemplo de códigoNo se garantiza que reemplazar
0
conNULL
un programa C válido, ya que no se define la suma entre dos punteros (y mucho menos de diferentes tipos de puntero). Hará que se emita un diagnóstico debido a una violación de restricción. Los operandos para sumar no serán válidos .En cuanto a C ++, las cosas son algo diferentes. La falta de una conversión implícita de
void*
a otros tipos de objetos significa queNULL
se definió históricamente como0
en el código C ++. En C ++ 03, probablemente podría salirse con la suya. Pero desde C ++ 11 se puede definirnullptr
legalmente como la palabra clave . Ahora nuevamente produce un error, yastd::nullptr_t
que no se puede agregar a los tipos de puntero.Si
NULL
se define comonullptr
entonces, incluso su experimento se vuelve inválido. No hay conversión destd::nullptr_t
a entero. Es por eso que se considera una constante de puntero nulo más segura.fuente
NULL
en ambos idiomas.0
un puntero nulo constante: "evidentemente como un soplo a todo el código C mal escrito existente que hizo suposiciones incorrectas"Las reglas varían entre idiomas y sus versiones. En algunos casos pueden los y en otros, no se puede. De todos modos, no deberías . Si tienes suerte, tu compilador te avisará cuando lo intentes o incluso mejor, no compiles.
En C ++, antes de C ++ 11 (cita de C ++ 03):
Tiene poco sentido usar una constante de puntero nulo como un entero. Sin embargo...
Entonces, técnicamente funcionaría incluso si no tiene sentido. Debido a este tecnicismo, puede encontrar programas mal escritos que abusan
NULL
.Desde C ++ 11 (cita del último borrador):
A
std::nullptr_t
no es convertible a un entero, por lo que usarloNULL
como un entero funcionaría solo condicionalmente, dependiendo de las elecciones realizadas por la implementación del lenguaje.PS
nullptr
es un valor de tipostd::nullptr_t
. A menos que necesite que su programa se compile en versiones anteriores a C ++ 11, siempre debe usarlo ennullptr
lugar deNULL
.C es un poco diferente (citas del borrador C11 N1548):
Entonces, el caso es similar a publicar C ++ 11, es decir, el abuso de las
NULL
obras condicionalmente dependiendo de las elecciones realizadas por la implementación del lenguaje.fuente
Sí , aunque dependiendo de la implementación, es posible que necesite un reparto. Pero sí, es 100% legítimo, de lo contrario.
Aunque es muy, muy, muy mal estilo (¿no hace falta decirlo?).
NULL
es, o era, en realidad no C ++, es C. Sin embargo, el estándar tiene , como para muchos legados en C, dos cláusulas ([diff.null] y [support.types.nullptr]) que técnicamente hacenNULL
C ++. Es una constante de puntero nulo definida por la implementación . Por lo tanto, incluso si es un mal estilo, técnicamente es tan C ++ como puede ser.Como se señala en la nota al pie , las posibles implementaciones podrían ser
0
o0L
, pero no(void*)0
.NULL
podría, por supuesto (el estándar no lo dice explícitamente, pero es prácticamente la única opción que queda después0
o0L
) sernullptr
. Ese casi nunca es el caso, pero es una posibilidad legal.La advertencia que le mostró el compilador demuestra que, de hecho, no es compatible (a menos que haya compilado en modo C). Porque, bueno, de acuerdo con la advertencia, convirtió un puntero nulo (no
nullptr
cuál sería denullptr_t
, lo que sería distinto), por lo que aparentemente la definición de síNULL
es(void*)0
, lo que puede no ser.De cualquier manera, tiene dos posibles casos legítimos (es decir, el compilador no está roto). O (el caso realista),
NULL
es algo como0
o0L
, entonces tienes "cero o uno" conversiones al número entero, y que son buenos para ir.O
NULL
es de hechonullptr
. En ese caso, tiene un valor distinto que tiene garantías sobre la comparación, así como conversiones claramente definidas de enteros, pero desafortunadamente no a enteros. Sin embargo, tiene una conversión claramente definida abool
(que resulta enfalse
), ybool
tiene una conversión claramente definida a entero (que resulta en0
).Desafortunadamente, son dos conversiones, por lo que no está dentro de "cero o uno" como se señala en [conv]. Por lo tanto, si su implementación se define
NULL
comonullptr
, entonces tendrá que agregar una conversión explícita para que su código sea correcto.fuente
De las preguntas frecuentes de C:
fuente
Descargo de responsabilidad: no sé C ++. Mi respuesta no está destinada a aplicarse en el contexto de C ++
'\0'
es unint
valor cero, solo 100% exactamente igual0
.En el contexto de los punteros ,
0
yNULL
son 100% equivalentes:son todos 100% equivalentes.
Nota sobre
ptr + NULL
El contexto de no
ptr + NULL
es el de los punteros. No existe una definición para la adición de punteros en el lenguaje C; Se pueden sumar (o restar) punteros y enteros. En caso de que o sea un puntero, el otro debe ser un número entero, por lo que es efectivo o dependiendo de las definiciones y se pueden esperar varios comportamientos: todo funciona, advertencia de conversión entre el puntero y el número entero, falla al compilar, .. .ptr + NULL
ptr
NULL
ptr + NULL
(int)ptr + NULL
ptr + (int)NULL
ptr
NULL
fuente
#define NULL (void *)0
antes. ¿Estás seguro de que NULL y 0 simple son 100% equivalentes?ptr + NULL
no se utilizaNULL
en el contexto de los punterosnullptr
es, pero((void*)0)
y0
(o'\0'
) son equivalentes en el contexto de los punteros ...if (ptr == '\0' /* or equivalent 0, NULL */)
No, ya no se prefiere usar
NULL
(antigua forma de inicialización del puntero).Desde C ++ 11:
La palabra clave
nullptr
denota el puntero literal. Es un valor de tipo std :: nullptr_t. Existen conversiones implícitas de unnullptr
valor de puntero nulo de cualquier tipo de puntero y cualquier tipo de puntero a miembro. Existen conversiones similares para cualquier constante de puntero nulo, que incluye valores de tipostd::nullptr_t
, así como la macroNULL
.https://en.cppreference.com/w/cpp/language/nullptr
En realidad, std :: nullptr_t es el tipo de lo literal puntero nulo,
nullptr
. Es un tipo distinto que no es en sí mismo un tipo de puntero o un puntero al tipo de miembro.Salida:
fuente