x64 tipos sistema que procesadores procesador operativo enteros definicion datos arquitectura c gcc type-conversion

tipos - sistema operativo de 64 bits procesador x64



Transmitir de una dirección de 32 bits a un entero de 64 bits produce resultados inesperados (1)

Esta es la implementación definida según el borrador de la sección estándar C99 6.3.2.3 Punteros que dice:

Cualquier tipo de puntero se puede convertir a un tipo entero. Excepto como se especificó previamente, el resultado está definido por la implementación. Si el resultado no se puede representar en el tipo entero, el comportamiento no está definido. El resultado no necesita estar en el rango de valores de ningún tipo entero.

gcc documenta su implementación aquí :

El resultado de convertir un puntero a un entero o viceversa (C90 6.3.4, C99 y C11 6.3.2.3).

  • Una conversión de puntero a entero descarta los bits más significativos si la representación del puntero es mayor que el tipo entero, sign-extends1 si la representación del puntero es menor que el tipo entero, de lo contrario los bits no se modificarán.

  • Un molde de entero a puntero descarta los bits más significativos si la representación del puntero es menor que el tipo entero, se extiende de acuerdo con la firma del tipo entero si la representación del puntero es mayor que el tipo entero, de lo contrario los bits no se modifican.

Alternativamente, puede usar uinitptr_t suponiendo que stdint.h está disponible, que es un entero sin signo que puede contener un valor de puntero:

#include <stdint.h> #include <inttypes.h> uintptr_t ip = &i ; printf("0x%016" PRIxPTR "/n", ip ) ;

Esta pregunta ya tiene una respuesta aquí:

Dado el siguiente programa:

#include <stdio.h> int main(int argc, char** argv) { int i; void* p = &i; printf("No cast, using %%p: %p/n", p); printf("Cast to unsigned long using conversion %%lx: %lx/n", (unsigned long) p); printf("Cast to unsigned long long using conversion %%llx: %llx/n", (unsigned long long) p); printf("Cast to unsigned long then unsigned long long using conversion %%llx: %llx/n", (unsigned long long) (unsigned long) p); return 0; }

¿Cuál esperaría que fuera la salida? Compilando con GCC 4.4.7 y ejecutando el programa dado el siguiente resultado:

No cast, using %p: 0xbf8aa3d8 Cast to unsigned long using conversion %lx: bf8aa3d8 Cast to unsigned long long using conversion %llx: ffffffffbf8aa3d8 Cast to unsigned long then unsigned long long using conversion %llx: bf8aa3d8

Compilar con la versión 3.4 de clang y ejecutar el programa produce lo que realmente esperaría:

No cast, using %p: 0xbfa64234 Cast to unsigned long using conversion %lx: bfa64234 Cast to unsigned long long using conversion %llx: bfa64234 Cast to unsigned long then unsigned long long using conversion %llx: bfa64234

Parece que GCC ha rellenado los bits más significativos con 1 en lugar de 0 al convertir directamente de puntero a largo sin signo. ¿Es esto un error en GCC?