pasar numero notacion metodo complemento como circuito calcula ca2 binario c types casting type-conversion

numero - Extensión de signo inesperado de puntero int32 o 32bit cuando se convierte a uint64



metodo de complemento a 2 (4)

Del estándar C99 (§6.3.2.3 / 6):

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.

Por lo tanto, deberá encontrar la documentación de su compilador que cuente sobre eso.

cl.exe /W4 este código usando Visual Studio 2010 ( cl.exe /W4 ) como un archivo C:

int main( int argc, char *argv[] ) { unsigned __int64 a = 0x00000000FFFFFFFF; void *orig = (void *)0xFFFFFFFF; unsigned __int64 b = (unsigned __int64)orig; if( a != b ) printf( " problem/ta: %016I64X/tb: %016I64X/n", a, b ); return; }

No hay advertencias y el resultado es:

problema a: 00000000FFFFFFFF b: FFFFFFFFFFFFFFFF

Supongo que int orig = (int)0xFFFFFFFF sería menos controvertido ya que no estoy asignando un puntero a un entero. Sin embargo, el resultado sería el mismo.

¿Puede alguien explicarme en qué parte del estándar C está cubierto que el signo original se extienda de 0xFFFFFFFF a 0xFFFFFFFFFFFFFFFF?

Había asumido que (unsigned __int64)orig se convertiría en 0x00000000FFFFFFFF. Parece que la conversión es primero al tipo __int64 firmado y luego se convierte en unsigned?

EDITAR: Esta pregunta ha sido respondida en que los punteros son signo extendido, por lo que veo este comportamiento en gcc y msvc. Sin embargo, no entiendo por qué cuando hago algo como (unsigned __int64)(int)0xF0000000 , el signo se extiende a 0xFFFFFFFFF0000000 pero (unsigned __int64)0xF0000000 no muestra lo que quiero, que es 0x00000000F0000000.

EDITAR: una respuesta a la edición anterior. La razón por la que (unsigned __int64)(int)0xF0000000 está extendido el signo es porque, como señaló el usuario R :

La conversión de un tipo con signo (o cualquier tipo) a un tipo sin signo siempre se realiza a través del módulo de reducción uno más el valor máximo del tipo de destino.

Y en (unsigned __int64)0xF0000000 0xF0000000 comienza como un tipo entero sin signo porque no puede caber en un tipo entero. Luego, el tipo ya sin firmar se convierte unsigned __int64 .

Así que la conclusión de esto para mí es con una función que devuelve un puntero de 32 bits o de 64 bits como unsigned __int64 para comparar. Primero debo convertir el puntero de 32 bits en mi aplicación de 32 bits a un tipo sin firmar antes de promocionar a unsigned __int64 . El código resultante se ve así (pero, ya sabes, mejor):

unsigned __int64 functionidontcontrol( char * ); unsigned __int64 x; void *y = thisisa32bitaddress; x = functionidontcontrol(str); if( x != (uintptr_t)y )



EDITAR de nuevo: Esto es lo que encontré en el estándar C99: 6.3.1.3 enteros con signo y sin signo

  • 1 Cuando un valor con tipo entero se convierte a otro tipo entero distinto de _Bool, si el valor puede representarse con el tipo nuevo, no se modifica.
  • 2 De lo contrario, si el nuevo tipo no está firmado, el valor se convierte al agregar o restar repetidamente uno más que el valor máximo que se puede representar en el nuevo tipo hasta que el valor esté en el rango del nuevo tipo.49)
  • 3 De lo contrario, el nuevo tipo se firma y el valor no se puede representar en él; el resultado es definido por la implementación o se genera una señal definida por la implementación.
  • 49) Las reglas describen la aritmética en el valor matemático, no el valor de un tipo dado de expresión.

La conversión de un puntero a / desde un entero está definida por la implementación.

Así es como lo hace gcc, es decir, su signo se extiende si el tipo entero es más grande que el tipo de puntero (esto sucederá independientemente del entero que se firme o no, simplemente porque así es como gcc decidió implementarlo).

Presumiblemente msvc se comporta de manera similar. Editar, lo más parecido que puedo encontrar en MSDN es esto / esto , lo que sugiere que la conversión de punteros de 32 bits a 64 bits también se extienda.


Las constantes enteras (p. Ej., 0x00000000FFFFFFFF ) son enteros con signo por defecto, y por lo tanto pueden experimentar extensión de signo cuando se asignan a una variable de 64 bits. Intente reemplazar el valor en la línea 3 con:

0x00000000FFFFFFFFULL


Use esto para evitar la extensión del letrero:

unsigned __int64 a = 0x00000000FFFFFFFFLL;

Tenga en cuenta la L en el extremo. Sin esto, se interpreta como un número firmado de 32 bits (-1) y luego se envía.