¿Se me permite usar el NULLpuntero 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
NULLde esta manera? - ¿Hay algo de malo en usar
NULLcomo 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, \0y 0es, pero no obtuve la información concisa de allí, si es bastante permisible y también correcto usarlo NULLcomo valor para operar en asignaciones y otras operaciones aritméticas.

Respuestas:
No , no es seguro hacerlo.
NULLes 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 tipointy valor 0, deletreela0.Sí, en cualquier implementación donde se
NULLexpande 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
-Werroropció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 hechoNULLdebe ser de tipoint, pero en versiones posteriores puede ser (y generalmente lo es)nullptr_t.void*aintes un comportamiento indefinido. No lo es; Es el comportamiento de implementación especificado.NULLes un puntero nulo constante. En C podría ser una expresión constante entera con valor0o una expresión de ese tipo convertida envoid*, con la última más probable. Lo que significa que no puede asumir que se usaNULLindistintamente con cero. Por ejemplo, en este ejemplo de códigoNo se garantiza que reemplazar
0conNULLun 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 queNULLse definió históricamente como0en el código C ++. En C ++ 03, probablemente podría salirse con la suya. Pero desde C ++ 11 se puede definirnullptrlegalmente como la palabra clave . Ahora nuevamente produce un error, yastd::nullptr_tque no se puede agregar a los tipos de puntero.Si
NULLse define comonullptrentonces, incluso su experimento se vuelve inválido. No hay conversión destd::nullptr_ta entero. Es por eso que se considera una constante de puntero nulo más segura.fuente
NULLen ambos idiomas.0un 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_tno es convertible a un entero, por lo que usarloNULLcomo un entero funcionaría solo condicionalmente, dependiendo de las elecciones realizadas por la implementación del lenguaje.PS
nullptres un valor de tipostd::nullptr_t. A menos que necesite que su programa se compile en versiones anteriores a C ++ 11, siempre debe usarlo ennullptrlugar 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
NULLobras 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?).
NULLes, 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 hacenNULLC ++. 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
0o0L, pero no(void*)0.NULLpodría, por supuesto (el estándar no lo dice explícitamente, pero es prácticamente la única opción que queda después0o0L) 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
nullptrcuál sería denullptr_t, lo que sería distinto), por lo que aparentemente la definición de síNULLes(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),
NULLes algo como0o0L, entonces tienes "cero o uno" conversiones al número entero, y que son buenos para ir.O
NULLes 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), ybooltiene 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
NULLcomonullptr, 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 unintvalor cero, solo 100% exactamente igual0.En el contexto de los punteros ,
0yNULLson 100% equivalentes:son todos 100% equivalentes.
Nota sobre
ptr + NULLEl contexto de no
ptr + NULLes 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 + NULLptrNULLptr + NULL(int)ptr + NULLptr + (int)NULLptrNULLfuente
#define NULL (void *)0antes. ¿Estás seguro de que NULL y 0 simple son 100% equivalentes?ptr + NULLno se utilizaNULLen el contexto de los punterosnullptres, 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
nullptrdenota el puntero literal. Es un valor de tipo std :: nullptr_t. Existen conversiones implícitas de unnullptrvalor 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