2010-05-14 8 views
19

Leí sobre el sufijo específico de Microsoft "i64" para las constantes enteras. Quiero hacer un cambio sin firma a un ULONGLONG.
ULONGLONG bigNum64 = 0x800000000000000i64 >> myval;¿Cómo se especifica un int constreño de 64 bits 0x8000000000000000 en VS2008?

En C normal, yo usaría el sufijo "U", p. la operación similar de 32 bits sería
ULONG bigNum32 = 0x80000000U >> myval;

NO deseo que la extensión del signo del complemento 2 se propague a través de los bits altos. Quiero un cambio sin signo en un número de const de 64 bit. Creo que mi primera declaración va a hacer un cambio FIRMADO correcto.

Intenté 0x800000000000000i64U y 0x800000000000000u64 pero me dieron errores del compilador.

+2

En mi Visual Studio, 'limits.h' tiene la sintaxis' 0xffffffffffffffffui64', por lo que '0x800000000000000ui64' debería funcionar. Sin embargo, es una versión más nueva, por lo que tal vez no funcionó en Visual Studio 2008. – anatolyg

+1

@MM: 'U' puede ser' unsigned int', 'unsigned long int', o' unsigned long long int' para un entero hexadecimal constante. 'UL' puede ser' unsigned long int' o 'unsigned long long int'. Ver 6.4.4.1 del estándar C (o 2.14.3 del estándar C++). Dado eso, no creo que el ejemplo del PO sea incorrecto o necesite modificación. – Cornstalks

+0

Esta es una pregunta anterior. En C++ 11, no creo que sea necesario ningún sufijo. Solo un tipo integral sin signo de 64 bits puede contener esa constante. Un unsigned long long debe tener al menos 64 bits, y eso está en la lista de tipos que el compilador debe probar para un literal en formato hexadecimal. http://en.cppreference.com/w/cpp/language/integer_literal –

Respuesta

29

Puede usar el sufijo ull, que es la forma estándar (C99 y C++ 0x) para especificar un literal entero unsigned long long, y un long long tiene al menos 64 bits.

+0

¡¡Eso funciona !! ¡Gracias! – franji1

+0

** Advertencia del compilador ** '-Wlong-long' se puede deshabilitar en la línea de comando del compilador o en el código con' #pragma Diagnóstico de GCC ignorado "-Wlong-long" '. [Aquí hay un buen ejemplo] (http://stackoverflow.com/a/16062548/673991) de hacer esto temporalmente para una sección de código. –

+0

@ BobStein-VisiBone: no recibirás ninguna advertencia sobre nada relacionado con 'long long' si estás compilando en modo C99 o superior. – AnT

0

Aquí manera:

int main() 
{ 
    uint64_t val1=0x1p63; //1 * 2**63 
    uint64_t val2=((uint64_t)0x1p63)-1; //0x1p63 is a float constant 
    uint64_t val3= ((uint64_t)0x1p63) >> 2; 
    cout << hex << "val1=" << val1 << " val2=" << val2 << " val3=" << val3 << endl; 
    return 0; 
} 

val1 val2 = 8000000000000000 = 7fffffffffffffff val3 = 2000000000000000

5

divertido lo suficiente, pero que en realidad no necesita añadir ningún sufijo a su constante hexadecimal con el fin de debe ser tratado correctamente. Sección 6.4.4.1 de la norma C y la sección 2.14.3 de la norma C++ contiene la siguiente tabla:

Suffix  | Decimal Constant  | Octal or Hexadecimal Constant 
-------------+------------------------+------------------------------ 
none   | int     | int 
      | long int    | unsigned int 
      | long long int   | long int 
      |      | unsigned long int 
      |      | long long int 
      |      | unsigned long long int 
-------------+------------------------+------------------------------ 
u or U  | unsigned int   | unsigned int 
      | unsigned long int  | unsigned long int 
      | unsigned long long int | unsigned long long int 
-------------+------------------------+------------------------------ 
l or L  | long int    | long int 
      | long long int   | unsigned long int 
      |      | long long int 
      |      | unsigned long long int 
-------------+------------------------+------------------------------ 
Both u or U | unsigned long int  | unsigned long int 
and l or L | unsigned long long int | unsigned long long int 
-------------+------------------------+------------------------------ 
ll or LL  | long long int   | long long int 
      |      | unsigned long long int 
-------------+------------------------+------------------------------ 
Both u or U | unsigned long long int | unsigned long long int 
and ll or LL |      | 

Esta tabla nos dice qué tipo una constante entera tendrá. El tipo de constante entera será el primer tipo en el que se ajuste el valor.

Esto significa que el compilador iterará a través de los siguientes tipos de la constante hexadecimal 0x800000000000000 (no tiene sufijo, por lo que utiliza la fila "ninguno" y es una constante hexadecimal, por lo que utiliza la columna "Constante hexadecimal"), y utilizará el primer tipo que puede almacenar ese valor *:

  1. int: no, un entero de 32 bits no puede almacenar este valor.
  2. unsigned int: No, un entero sin signo de 32 bits no puede almacenar este valor.
  3. long int: No, un entero con signo de 32 bits no puede almacenar este valor.
  4. unsigned long int: No, un entero sin signo de 32 bits no puede almacenar este valor.
  5. long long int: No, un entero con signo de 64 bits no puede almacenar este valor.
  6. unsigned long long int: Sí, un entero de 64 bits sin signo puede almacenar este valor. Como este es el primer tipo que puede almacenar completamente el valor, este es el tipo que tendrá la constante entera.

Por lo tanto, para responder a su pregunta de "¿Cómo puedo escribir y utilizar el valor 0x800000000000000 y asegúrese de que el compilador no sirve para tratar el bit alto como un bit de signo?": Simplemente acaba de escribir unsigned long long value = 0x800000000000000.

Si desea hacer una aritmética bit a bit con el valor, puede continuar y hacer eso (es decir, simplemente escriba 0x800000000000000 >> myval). Tiene la garantía de que no será tratado como un entero con signo desbordado, y su desplazamiento a la derecha no hará ninguna extensión de signo porque es un valor positivo.

* Estoy asumiendo que int es de 32-bits, long es de 32-bits, y long long es de 64-bits. Tenga en cuenta que su compilador puede usar diferentes tamaños de bits para estos tipos, lo que puede cambiar el resultado final (aunque el proceso seguirá siendo el mismo).

+0

Sin embargo, debes tener cuidado. Si quiere declarar unsigned long long sin sufijo, se meterá en problemas: considere 'printf ("% lx \ n ", (0x40000000 <<1)>> 1);' El desplazamiento hacia la izquierda/derecha debería devolver 0x40000000, pero si ejecuta esto, obtendrá 0xc0000000. –

Cuestiones relacionadas