Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

339
Views
Cuando NULL no es todos cero bits, ¿un valor de puntero de todos cero bits también es 'falso'?

Sé que los compiladores de C no están obligados a usar todos los ceros para la representación de bits de NULL , pero *son * requeridos por el estándar para hacer que NULL se evalúe como falso en contextos/comparaciones booleanas. Por lo tanto, el segundo printf en el programa a continuación siempre generará false .

Pero lo que quiero saber es: en los sistemas donde NULL es *no * todo ceros, ¿un valor de puntero que *es * todo ceros también se evaluará como falso en contextos/comparaciones booleanas? En otras palabras, ¿el primer printf en el programa a continuación será true ?

O preguntado de una manera ligeramente diferente: ¿puedo confiar en calloc para producir un valor de puntero que siempre se evaluará como falso en contextos/comparaciones booleanas? La primera respuesta a esta pregunta usa memset para borrar los bits de un long* llamado y , luego continúa diciendo que y==0 es UB porque y puede ser una "representación trampa" (sea lo que sea). calloc también está borrando bits, por lo que tal vez o->p en la primera printf también es UB.


 #include <stdio.h> #include <stdlib.h> #include <assert.h> typedef struct { void * p; } obj; int main() { obj * o = calloc(sizeof(obj), 1); assert(o); // assume successful allocation printf("%s\n", o->p ? "true" : "false"); // 1st: could print "true"? Is o->p UB? o->p = NULL; printf("%s\n", o->p ? "true" : "false"); // 2nd: always prints "false" return 0; }
over 4 years ago · Santiago Trujillo
4 answers
Answer question

0

Hay una gran discusión sobre NULL y 0 en la primera respuesta a esta pregunta: ¿Cuál es la diferencia entre NULL, '\0' y 0?

El remate en esa respuesta es:

Tenga en cuenta que lo que es un puntero nulo en el lenguaje C. No importa la arquitectura subyacente. Si la arquitectura subyacente tiene un valor de puntero nulo definido como dirección 0xDEADBEEF, entonces depende del compilador solucionar este problema.

… Incluso en esta arquitectura divertida, las siguientes formas siguen siendo formas válidas de verificar un puntero nulo:

 if (!pointer) if (pointer == NULL) if (pointer == 0)

Y en la segunda respuesta a la misma pregunta...

Una expresión constante de tipo int con el valor 0, o una expresión de este tipo, convertida en tipo void * es una constante de puntero nulo, que si se convierte en un puntero se convierte en un puntero nulo. Está garantizado por el estándar para comparar desigual a cualquier puntero a cualquier objeto o función.

(Respuesta corta, sí, puede buscar un puntero NULL con if (!ptr) ).

over 4 years ago · Santiago Trujillo Report

0

typedef struct { void * p; } obj; obj * o = calloc(sizeof(obj), 1); assert(o); // Let us set aside the case of a failed allocation printf("%s\n", o->p ? "true" : "false"); // 1st: could print "true" ?

¿puedo confiar en calloc para producir un valor de puntero que siempre se evaluará como falso en contextos/comparaciones booleanos?

No: la salida podría ser "true" . *1 .

El patrón de bits de todos los ceros, como puntero, puede no ser un puntero nulo .

7.22.3.2 La función calloc
2 La función calloc asigna espacio para una matriz de objetos nmemb , cada uno de los cuales tiene un tamaño. El espacio se inicializa a todos los bits cero.301)
Nota al pie 301) Tenga en cuenta que no es necesario que sea lo mismo que la representación del cero de punto flotante o una constante de puntero nulo.


Ejemplo: una implementación solo puede tener una única codificación de puntero nulo con un patrón de bits de todos unos. (void *)0 convierte el patrón de bits de todos los ceros int 0 en un void * de todos los unos. if (null_pointer) siempre es falso, independientemente del patrón de bits del puntero nulo .


*1 Sin embargo, prácticamente sí, la salida siempre es "false" . Las implementaciones son poco comunes en estos días que no usan todos los patrones de bits cero como un puntero nulo . El código altamente portátil no asumiría esta practicidad. Considere que un sistema novedoso antiguo o nuevo puede usar un patrón de cero bits como un puntero no nulo y, lamentablemente, romper muchas bases de código que asumen que un patrón de cero bits es un puntero nulo .

over 4 years ago · Santiago Trujillo Report

0

Respuesta central

Pero lo que quiero saber es: en los sistemas donde NULL es *no * todo ceros, ¿un valor de puntero que *es * todo ceros también se evaluará como falso en contextos/comparaciones booleanas?

En una implementación de C, el estándar C permite cualquiera de:

  • All-bits-zero es un puntero nulo y ningún otro patrón de bits lo es.
  • All-bits-zero es un puntero nulo y uno o más patrones de bits lo son.
  • All-bits-zero no es un puntero nulo y uno o más patrones de bits sí lo son.

En otras palabras, una implementación de C puede designar uno o más patrones de bits para que sean punteros nulos, y esto puede incluir o no todos los bits cero. (Si la implementación de C permite que múltiples patrones de bits sean punteros nulos, debe asegurarse de que se comparen como iguales).

… ¿el primer printf en el programa a continuación será true ?

Se permite que imprima “verdadero”; el resultado de calloc es memoria con todos los bits cero, e interpretar esa memoria como un void * puede dar como resultado un valor de puntero que no es un valor de puntero nulo.

Suplemento

… donde NULL es *no * todo ceros…

NULL es solo algo en el código fuente. Es 0 o ((void *) 0) o un equivalente. Dondequiera que se use como un puntero en el código fuente (es decir, está haciendo cosas normales como if (pointer != NULL) , no chapuzas como int x = 3 + NULL; ), el compilador lo convierte efectivamente en un puntero nulo. Es decir, si todos los bits cero no es un puntero nulo en la implementación de C, el compilador compilará el pointer != NULL en una comparación del pointer con algún patrón de bits que represente un puntero nulo.

Entonces, sus preguntas son todas sobre punteros nulos; no se trata de NULL .

… en sistemas donde…

La determinación final de lo que es un puntero nulo recae en la implementación de C, no en el sistema en el que se ejecuta. La implementación de AC puede representar punteros de la forma que desee y transformarlos según sea necesario al usar direcciones de máquina en las instrucciones.

over 4 years ago · Santiago Trujillo Report

0

Puede evitar este tipo de preguntas con un estilo de codificación explícito y defensivo.

si tiene un puntero _p, escriba construcciones como

 (_p==NULL)?(A):(B)

ahora cualquier lector sabe de inmediato que su intención es verificar si _p es igual a NULL e incluso en una máquina donde NULL puede ser diferente de un valor entero de 0, el compilador lo hará automáticamente de manera correcta. Además, un verificador de código estático ahora no le advertirá debido a que se basa en un comportamiento implícito.

 (_p)?(A):(B)

simplemente no lo está haciendo bien

pero aparte de eso, es una pregunta técnica interesante.

Una charla interesante del comité de C ++ de 2019 o 2020 reveló que incluso estos muchachos piensan en eliminar la compatibilidad con un comportamiento extraño e indefinido, que se necesitaba antes de 1970 para algunas arquitecturas 3-4. No hubo ningún uso conocido de este material en las últimas décadas, al menos que yo sepa. Como dice el primer comentario a sus preguntas: Difícilmente encontrará una máquina con tal problema, al menos fuera de un museo.

over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!