¿Podría hacer llanura int de 64 bits romper una gran cantidad de código razonable?

StackOverflow https://stackoverflow.com/questions/4559251

  •  14-10-2019
  •  | 
  •  

Pregunta

Hasta hace poco, había considerado la decisión de la mayoría de los implementadores de sistemas / vendedores para mantener llanura int 32 bits incluso en máquinas de 64 bits en una especie de verruga conveniente. Con C99 moderna tipos de tamaño fijo (int32_t y uint32_t, etc.) la necesidad de que haya un tipo entero estándar de cada tamaño de 8, 16, 32, y 64 desaparece en su mayoría, y parece que int podría también hacerse 64-bit.

Sin embargo, la mayor consecuencia real del tamaño de int sencillo en C proviene del hecho de que C esencialmente no tiene la aritmética de los tipos más pequeños de lo int. En particular, si int es mayor que 32 bits, el resultado de cualquier aritmética sobre los valores uint32_t tiene tipo signed int, que es bastante perturbador.

¿Es esta una buena razón para mantener int fijado de forma permanente a los 32 bits en implementaciones del mundo real? Me estoy inclinando hacia decir sí. Me parece como que podría haber una enorme clase de usos de uint32_t que se rompen cuando int es mayor de 32 bits. Incluso aplicando el complemento bit a bit o menos unario operador vuelve peligroso a menos que lanzas de nuevo a uint32_t.

Por supuesto, los mismos problemas se aplican a uint16_t y uint8_t en las implementaciones actuales, pero todo el mundo parece estar al tanto y se utiliza para el tratamiento de ellos como tipos "más pequeñas que las int".

¿Fue útil?

Solución

Como usted dice, creo que las reglas de la promoción son en realidad el asesino. uint32_t entonces a promover int y, de repente, se hubiera firmado la aritmética en el que casi todo el mundo espera sin firmar.

Esto sería ocultado sobre todo en los lugares donde se hacen volver simplemente la aritmética y la asigna a una uint32_t. Pero podría ser mortal en lugares en los que la comparación de las constantes. Si el código que se basa en este tipo de comparaciones sin hacer una conversión explícita es razonable, no sé. Fundición constantes como (uint32_t)1 puede llegar a ser bastante tedioso. Yo personalmente, al menos, siempre uso el sufijo para U constantes que quiero estar sin firmar, pero esto ya no es tan legible como me gustaría.

También tiene en cuenta que uint32_t etc, no están garantizados para existir. Ni siquiera uint8_t. La ejecución de dicha es una extensión de POSIX. Así que en ese sentido C como lenguaje está lejos de ser capaz de hacer ese movimiento.

Otros consejos

"razonable Código" ...

Bueno ... lo que pasa con el desarrollo es, que escribe y resuelve, y entonces funciona ... y luego se detiene!

Y tal vez he quemado mucho, así que mantenerse dentro de los límites de seguridad de ciertas características, y tal vez usted no ha sido quemado en que forma particular por lo que no se dan cuenta de que usted está confiando en algo que podría tipo de cambio.

O incluso que usted está confiando en un error.

En Olden Mac 68000 compiladores, int era de 16 bits de largo y era 32. Pero incluso entonces el código C existente supone más de un int fue de 32, lo que el código típico que encontraste en un grupo de noticias no funcionaría. (Ah, y Mac no tenía printf, pero estoy divagando.)

Por lo tanto, lo que quiero llegar es que sí, si cambia lo , a continuación, algunas cosas se romperán.

Con C99 moderna tipos de tamaño fijo (Int32_t y uint32_t, etc.) la necesidad para que haya un número entero estándar tipo de cada tamaño de 8, 16, 32, y 64 sobre todo desaparece,

C99 ha typedefs, no tipos de tamaño fijo de tamaño fijo. El C nativo entero tipos son todavía char, short, int, long, y long long. Ellos siguen siendo pertinentes.

El problema con ILP64 es que tiene una gran falta de correspondencia entre los tipos C y typedefs C99.

  • int8_t = Char
  • int16_t = corto
  • int32_t = tipo no estándar
  • int64_t = int, largo, o mucho, mucho

de 64 bits de programación Modelos: ¿Por LP64 :?

Por desgracia, el modelo hace ILP64 no proporciona una forma natural para describir tipos de datos de 32 bits, y deben recurrir a construcciones no portátiles como __int32 para describir tales tipos. Esto es probable que cause problemas prácticos en la producción de código que se puede ejecutar en 32 y 64 plataformas bits sin construcciones #ifdef. Ha sido posible portar grandes cantidades de LP64 código para modelos sin la necesidad para hacer tales cambios, mientras el mantenimiento de la inversión realizada en conjuntos de datos, incluso en casos en que la información de tipificación no se hizo externamente visible por la aplicación.

DEC Alpha y OSF / 1 Unix fue una de las primeras versiones de 64 bits de Unix, y se utiliza enteros de 64 bits - un ILP64 arquitectura (int significa, long y punteros eran todas las cantidades de 64 bits). Esto causó un montón de problemas.

Una de las cuestiones que he mencionado que no se ve - que es por eso que estoy respondiendo a todos después de tanto tiempo - es que si usted tiene un int de 64 bits, qué tamaño usted utilizar para short? Ambos 16 bits (el, cambio nada enfoque clásico) y 32 bits (el radical 'bueno, un short debe ser la mitad el tiempo que un int' enfoque) presentará algunos problemas.

Con los <stdint.h> y <inttypes.h> cabeceras C99, puede código de números enteros de tamaño fijo - si optar por ignorar las máquinas con números enteros de 36 bits o de 60 bits (que es al menos cuasi-legítimo). Sin embargo, la mayoría del código que no está escrito utilizando esos tipos, y hay típicamente profundamente arraigados y en gran parte oculta (pero fundamentalmente defectuoso) supuestos en el código que se molesta si se aparta de los modelos de las variaciones existentes.

modelo LLP64 ultraconservador de Aviso de Microsoft para Windows de 64 bits. Que fue elegido porque demasiado viejo código se rompería si el modelo de 32 bits fue cambiado. Sin embargo, el código que había sido portado a ILP64 o LP64 arquitecturas no estaba inmediatamente portátil para LLP64 debido a las diferencias. teóricos de la conspiración probablemente diría que fue elegido deliberadamente para que sea más difícil para el código escrito para Unix de 64 bits para ser portado a Windows de 64 bits. En la práctica, dudo que eso era más que un feliz (de Microsoft) de efectos secundarios; el código de Windows de 32 bits tuvo que ser revisado mucho que hacer uso del modelo LP64 también.

Hay un lenguaje de código que se rompería si enteros fueron 64-bits, y lo veo a menudo que creo que podría ser llamado razonable:

  • comprobar si un valor es negativo probando si ((val & 0x80000000) != 0)

Esto se encuentra comúnmente en la comprobación de los códigos de error. Muchas normas del código de error (como HRESULT de ventana) usos bit 31 para representar un error. Y el código de veces comprobará que el error ya sea mediante pruebas bit 31 o, a veces mediante la comprobación de si el error es un número negativo.

macros de Microsoft para probar HRESULT utilizar ambos métodos - y estoy seguro de que hay un montón de código por ahí que lo hace similar sin el uso de las macros SDK. Si MS se había trasladado a ILP64, esto sería un área que causó portar dolores de cabeza que se evitan completamente con el modelo LLP64 (o el modelo LP64).

. Nota: Si usted no está familiarizado con términos como "ILP64", consulte el mini-glosario al final de la respuesta

estoy bastante seguro de que hay una gran cantidad de código (no necesariamente orientado a Windows) por ahí que los usos llanura de edad-int a los códigos de error de retención, en el supuesto de que esos son enteros de 32 bits de tamaño. Y apuesto a que hay una gran cantidad de código con el esquema de estado de error que también utiliza los dos tipos de controles (< 0 y el bit 31 siendo conjunto) y que se rompería si se trasladó a una plataforma ILP64. Estos controles se podrían hacer para seguir funcionando correctamente en cualquier caso, si los códigos de error se construyeron con cuidado para que la extensión con signo se llevó a cabo, pero de nuevo, muchos de estos sistemas que he visto construcción de los valores de error por o-ing junto a un montón bitfields .

De todos modos, no creo que esto es un problema sin solución por cualquier medio, pero yo creo que es una codificación de la práctica bastante común que causaría una gran cantidad de código para requerir arreglar si se mueve hacia una plataforma ILP64.

Tenga en cuenta que yo también no creo que esto era una de las razones más importantes para Microsoft para elegir el modelo LLP64 (creo que la decisión fue impulsado en gran medida por la compatibilidad de datos binarios entre los procesos de 32 bits y de 64 bits, como mencionado en MSDN y en el blog de Raymond Chen ).


Mini-Glosario para la plataforma terminología modelo de programación de 64 bits:

  • ILP64: int, long, los punteros son de 64 bits de
  • LP64: long y punteros son de 64-bits, int es de 32-bits (? Utilizado por muchos (la mayoría) plataformas Unix)
  • LLP64: long long y punteros son de 64-bits, int y long permanecen 32-bits (usados ??en Win64)

Para obtener más información sobre los modelos de programación de 64 bits, ver "Modelos de programación de 64 bits: ¿Por LP64? "

Mientras que hago código no personalmente escribir así, apuesto a que es ahí en más de un lugar ... y por supuesto que va a romper si se cambia el tamaño de int.

int i, x = getInput();
for (i = 0; i < 32; i++)
{
    if (x & (1 << i))
    {
        //Do something
    }
}

Bueno, no es que esta historia es totalmente nuevo. "Con la mayoría de los ordenadores" Yo asumo que los ordenadores de sobremesa medias. Ya ha habido una transición de 16 bits a int 32 bits. ¿Hay algo en todo lo que dice la misma progresión no sucederá esta vez?

No particularmente. int es de 64 bits en algunas arquitecturas 64 bits (no x64).

La norma no garantiza realmente se obtiene 32 bits enteros, sólo que (u) int32_t puede contener uno.

Ahora bien, si usted está en función de int es del mismo tamaño que ptrdiff_t se puede romper.

Recuerde que C no garantiza que la máquina aún es una máquina binaria.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top