Sé que los estándares C y C ++ dejan muchos aspectos del lenguaje definidos por la implementación solo porque si hay una arquitectura con otras características, sería muy difícil o imposible escribir un compilador conforme estándar.
Sé que hace 40 años cualquier computadora tenía su propia especificación única. Sin embargo, no conozco ninguna arquitectura utilizada hoy en día donde:
CHAR_BIT != 8
signed
no es el complemento de dos (escuché que Java tenía problemas con este).- El punto flotante no cumple con IEEE 754 (Editar: quise decir "no en codificación binaria IEEE 754").
La razón por la que pregunto es que a menudo les explico a las personas que es bueno que C ++ no exija ningún otro aspecto de bajo nivel, como los tipos de tamaño fijo † . Es bueno porque, a diferencia de 'otros idiomas', hace que su código sea portátil cuando se usa correctamente (Edición: porque se puede portar a más arquitecturas sin requerir la emulación de aspectos de bajo nivel de la máquina, como por ejemplo, aritmética complementaria de dos en arquitectura de signo + magnitud) . Pero me siento mal porque no puedo señalar ninguna arquitectura específica yo mismo.
Entonces la pregunta es: ¿qué arquitecturas exhiben las propiedades anteriores?
† uint*_t
s son opcionales.
fuente
Respuestas:
Echa un vistazo a este
Servidores Unisys ClearPath Dorado
ofreciendo compatibilidad con versiones anteriores para personas que aún no han migrado todo su software Univac.
Puntos clave:
CHAR_BIT == 9
Sin embargo, no sé si ofrecen un compilador de C ++, pero podrían hacerlo .
Y ahora ha aparecido un enlace a una edición reciente de su manual en C:
Manual de referencia de programación del compilador Unisys C
La Sección 4.5 tiene una tabla de tipos de datos con 9, 18, 36 y 72 bits.
fuente
char*
yvoid*
deben ser del mismo tamaño, y lo suficientemente grande para contener cualquier otro puntero. El resto depende de la implementación.sizeof(int*) == 2
, pero los punteros lejanos también tenían un selector de 16 bitssizeof(void*) == 4
.sizeof(int*) != sizeof(char*)
aquí: ambos son 36 bits. Pero el selector de bytes en elchar*
está en los bits de orden superior, y se ignora enint*
. (Sin embargo, he usado otras máquinas, donde `sizeof (char *)> sizeof (int *).)void*
) siempre tenían el mismo tamaño. (Por supuesto, no podría convertir un puntero de funciónvoid*
, ya quevoid*
podría ser más pequeño. Pero de acuerdo con el estándar, tampoco puede hacerlo hoy.)Ninguno de sus supuestos es válido para mainframes. Para empezar, no conozco un mainframe que use IEEE 754: IBM usa punto flotante base 16, y ambos mainframes Unisys usan base 8. Las máquinas Unisys son un poco especiales en muchos otros aspectos: Bo ha mencionado el 2200 arquitectura, pero la arquitectura MPS es aún más extraña: palabras etiquetadas de 48 bits. (Si la palabra es un puntero o no, depende de un poco en la palabra). Y las representaciones numéricas están diseñadas para que no haya una distinción real entre coma flotante y aritmética integral: el punto flotante es base 8; no requiere normalización y, a diferencia de cualquier otro punto flotante que he visto, coloca el decimal a la derecha de la mantisa, en lugar de a la izquierda, y utiliza la magnitud con signo para el exponente (además de la mantisa). Con los resultados de que un valor de coma flotante integral tiene (o puede tener) exactamente la misma representación de bits que un entero de magnitud con signo. Y no hay instrucciones aritméticas de coma flotante: si los exponentes de los dos valores son ambos 0, la instrucción hace aritmética integral, de lo contrario, hace aritmética de coma flotante. (Una continuación de la filosofía de etiquetado en la arquitectura). Lo que significa que mientras
int
puede ocupar 48 bits, 8 de ellos deben ser 0 o el valor no se tratará como un entero.fuente
El cumplimiento total de IEEE 754 es raro en implementaciones de punto flotante. Y debilitar la especificación en ese sentido permite muchas optimizaciones.
Por ejemplo, el soporte de subnorm difiere entre x87 y SSE.
Las optimizaciones como fusionar una multiplicación y una suma que estaban separadas en el código fuente también cambian ligeramente los resultados, pero es una buena optimización en algunas arquitecturas.
O en x86, el cumplimiento estricto de IEEE puede requerir que se establezcan ciertos indicadores o transferencias adicionales entre los registros de punto flotante y la memoria normal para obligarlo a usar el tipo de punto flotante especificado en lugar de sus flotantes internos de 80 bits.
Y algunas plataformas no tienen flotantes de hardware y, por lo tanto, necesitan emularlos en software. Y algunos de los requisitos de IEEE 754 pueden ser costosos de implementar en software. En particular, las reglas de redondeo pueden ser un problema.
Mi conclusión es que no necesita arquitecturas exóticas para entrar en situaciones en las que no siempre quiere garantizar el cumplimiento estricto de IEEE. Por esta razón, pocos lenguajes de programación garantizan el estricto cumplimiento de IEEE.
fuente
long double
podría haber sido un tipo útil y de larga vida, ya que el único problema real con el que funcionaba malprintf
. El hecho de que el doble extendido almacene el 1 principal acelera explícitamente los cálculos en sistemas que no son FPU y también eliminaría la necesidad de un manejo especial de los valores normales en cualquier contexto que no sea conversiones hacia / desde otros tipos. Lástima que C lo hayaprintf
estropeado todo.Encontré este enlace que enumera algunos sistemas donde
CHAR_BIT != 8
. IncluyenY, por supuesto, hay una pregunta sobre Stack Overflow: ¿Qué plataformas tienen algo más que caracteres de 8 bits?
En cuanto a los sistemas que no son del complemento a dos, hay una lectura interesante en comp.lang.c ++. Moderada . Resumido: hay plataformas que tienen un complemento o representación de signo y magnitud.
fuente
CHAR_BIT=32
, y Texas Instruments DSP de TMS32F28xx tieneCHAR_BIT=16
. GCC 3.2 para PDP-10 tieneCHAR_BIT=9
. Creo que S / 360 también puede tener un carácter no de 8 bits.CHAR_BITS
es un duplicado parcial.Estoy bastante seguro de que los sistemas VAX todavía están en uso. No admiten IEEE de punto flotante; ellos usan sus propios formatos. Alpha admite los formatos de punto flotante VAX e IEEE.
Las máquinas de vectores Cray, como la T90, también tienen su propio formato de punto flotante, aunque los sistemas Cray más nuevos usan IEEE. (El T90 que utilicé fue retirado hace algunos años; no sé si alguno todavía está en uso activo).
El T90 también tenía / tiene algunas representaciones interesantes para punteros y enteros. Una dirección nativa solo puede apuntar a una palabra de 64 bits. Los compiladores de C y C ++ tenían CHAR_BIT == 8 (necesario porque ejecutaba Unicos, un sabor de Unix, y tenían que interactuar con otros sistemas), pero una dirección nativa solo podía apuntar a una palabra de 64 bits. Todas las operaciones a nivel de byte se sintetizaron por el compilador, y una
void*
ochar*
almacenan un desplazamiento en el alto orden 3 bits de la palabra de bytes. Y creo que algunos tipos enteros tenían bits de relleno.Los mainframes de IBM son otro ejemplo.
Por otro lado, estos sistemas particulares no necesariamente excluyen cambios al estándar del lenguaje. Cray no mostró ningún interés particular en actualizar su compilador de C a C99; presumiblemente lo mismo se aplica al compilador de C ++. Que podría ser razonable para apretar los requisitos para implementaciones alojadas, como requerir CHAR_BIT == 8, el formato de punto flotante IEEE, si no la semántica completos, y de complemento a 2 sin bits de relleno para los enteros con signo. Los sistemas antiguos podrían continuar admitiendo estándares de lenguaje anteriores (C90 no murió cuando salió C99), y los requisitos podrían ser más flexibles para implementaciones independientes (sistemas integrados) como DSP.
Por otro lado, puede haber buenas razones para que los sistemas futuros hagan cosas que hoy se considerarían exóticas.
fuente
unsigned
tipos integrales serán un gran problema, mientras que la aritmética con signo estará bien.CHAR_BITS
Según el código fuente de gcc :
CHAR_BIT
son16
bits para arquitecturas 1750a , dsp16xx .CHAR_BIT
son24
bits para la arquitectura dsp56k .CHAR_BIT
son32
bits para la arquitectura c4x .Puede encontrar más fácilmente haciendo:
o
si
CHAR_TYPE_SIZE
se define adecuadamenteCumplimiento IEEE 754
Si la arquitectura de destino no admite instrucciones de coma flotante, gcc puede generar software alternativo que no cumple con el estándar por defecto.
-funsafe-math-optimizations
Además, se pueden usar opciones especiales (como bruja también deshabilita la preservación de signos para ceros).fuente
La representación binaria IEEE 754 era poco común en las GPU hasta hace poco, ver Paranoia de punto flotante de GPU .
EDITAR: se ha planteado una pregunta en los comentarios sobre si el punto flotante de GPU es relevante para la programación informática habitual, sin relación con los gráficos. ¡Oh sí! La mayoría de las cosas de alto rendimiento calculadas industrialmente hoy en día se realizan en GPU; la lista incluye IA, minería de datos, redes neuronales, simulaciones físicas, pronóstico del tiempo y mucho más. Uno de los enlaces en los comentarios muestra por qué: un orden de magnitud de ventaja de coma flotante de las GPU.
Otra cosa que me gustaría agregar, que es más relevante para la pregunta de OP: ¿qué hicieron las personas hace 10-15 años cuando el punto flotante de GPU no era IEEE y cuando no había API como OpenCL o CUDA para programar GPU? ¡Lo creas o no, los primeros pioneros en informática de GPU lograron programar GPU sin una API para hacerlo ! Conocí a uno de ellos en mi empresa. Esto es lo que hizo: codificó los datos que necesitaba para calcular como una imagen con píxeles que representaban los valores en los que estaba trabajando, luego usó OpenGL para realizar las operaciones que necesitaba (como "desenfoque gaussiano" para representar una convolución con una distribución normal , etc.) y decodificó la imagen resultante nuevamente en una matriz de resultados. ¡Y esto todavía fue más rápido que usar CPU!
Cosas como esa es lo que llevó a NVidia a finalmente hacer que sus datos binarios internos sean compatibles con IEEE e introducir una API orientada a la computación en lugar de la manipulación de imágenes.
fuente
int f(int n) { return n <= 1 ? 1 : n * f(n-1); }
en CUDA? Si no, las GPU no son relevantes para esta pregunta (que pregunta sobre los comités C y C ++).