para library juce gui framework cross con c++ c cross-platform

c++ - library - ¿Qué plataformas tienen algo más que un char de 8 bits?



wx widget (12)

¿Qué tipo de consideración vale la pena dar a las plataformas con caracteres no de 8 bits?

los números mágicos ocurren, por ejemplo, al cambiar;

la mayoría de estos pueden manejarse de manera simple utilizando CHAR_BIT y, por ejemplo, UCHAR_MAX en lugar de 8 y 255 (o similar).

esperemos que su implementación los defina :)

esos son los problemas "comunes" .....

Otro problema indirecto es decir que tienes:

struct xyz { uchar baz; uchar blah; uchar buzz; }

esto podría "solo" tomar (el mejor de los casos) 24 bits en una plataforma, pero podría tomar, por ejemplo, 72 bits en otro lugar .....

si cada uchar tenía "banderas de bits" y cada uchar solo tenía 2 "bits" significativos o banderas que estaba usando actualmente, y usted solo las organizó en 3 uchas para "claridad", entonces podría ser relativamente "más derrochador", por ejemplo, en una plataforma con uchars de 24 bits .....

nada que los bitfields no puedan resolver, pero tienen otras cosas de las que deben cuidarse ...

en este caso, una sola enumeración podría ser una forma de obtener el entero de tamaño "más pequeño" que realmente necesita ...

tal vez no sea un ejemplo real, pero algo así me "mordió" al portar / jugar con algún código .....

solo el hecho de que si una uchar es tres veces más grande de lo que se espera "normalmente", 100 de esas estructuras podrían desperdiciar mucha memoria en algunas plataformas ... donde "normalmente" no es un gran problema ... .

entonces las cosas aún pueden estar "rotas" o en este caso "perder mucha memoria muy rápido" debido a la suposición de que una uchar "no es muy derrochadora" en una plataforma, en relación con la RAM disponible, que en otra plataforma ... ..

el problema podría ser más prominente, por ejemplo, para los ints u otros tipos, por ejemplo, usted tiene una estructura que necesita 15 bits, por lo que la inserta en un int, pero en otra plataforma, un int es de 48 bits o lo que sea .... .

"normalmente" podrías dividirlo en 2 uchas, pero por ejemplo con una uchar de 24 bits solo necesitarías una .....

entonces una enumeración podría ser una mejor solución "genérica" ​​...

Depende de cómo está accediendo a esos bits, aunque :)

por lo tanto, podría haber "fallas de diseño" que le revienten la cabeza ... incluso si el código aún funcionara / funcionara bien, independientemente del tamaño de una uchar o uint ...

hay cosas como esta a tener en cuenta, aunque no haya "números mágicos" en su código ...

espero que esto tenga sentido :)

De vez en cuando, alguien en SO señala que char (también conocido como ''byte'') no es necesariamente 8 bits .

Parece que el carácter de 8 bits es casi universal. Hubiera pensado que para las plataformas convencionales, es necesario tener un char 8 bits para garantizar su viabilidad en el mercado.

Tanto ahora como históricamente, ¿qué plataformas usan un char que no es de 8 bits y por qué difieren de los 8 bits "normales"?

Al escribir código, y pensar en soporte multiplataforma (por ejemplo, para bibliotecas de uso general), ¿qué tipo de consideración vale la pena dar a las plataformas con caracteres no de 8 bits?

En el pasado, me encontré con algunos DSP de Analog Devices para los que char es de 16 bits. Los DSP son un poco de arquitectura de nicho, supongo. (Por otra parte, en ese momento, el ensamblador codificado a mano superaba fácilmente lo que los compiladores de C disponibles podían hacer, así que realmente no obtuve mucha experiencia con C en esa plataforma).


Al escribir código, y pensar en soporte multiplataforma (por ejemplo, para bibliotecas de uso general), ¿qué tipo de consideración vale la pena dar a las plataformas con caracteres no de 8 bits?

No es tanto que sea "digno de consideración" a algo, ya que está jugando según las reglas. En C ++, por ejemplo, el estándar dice que todos los bytes tendrán "al menos" 8 bits. Si su código asume que los bytes tienen exactamente 8 bits, está violando el estándar.

Esto puede parecer tonto ahora - "¡ por supuesto, todos los bytes tienen 8 bits!", Lo escuché decir. Pero muchas personas muy inteligentes han confiado en suposiciones que no eran garantías, y luego todo se rompió. La historia está repleta de tales ejemplos.

Por ejemplo, la mayoría de los desarrolladores de principios de los 90 supusieron que un retraso de temporización de CPU no-operativa particular que tomara un número fijo de ciclos tomaría una cantidad fija de tiempo de reloj, porque la mayoría de las CPU consumidoras eran aproximadamente equivalentes en potencia. Lamentablemente, las computadoras se aceleraron rápidamente. Esto generó el surgimiento de cajas con botones "Turbo", cuyo propósito, irónicamente, era ralentizar la computadora para que los juegos que usan la técnica de retardo de tiempo pudieran reproducirse a una velocidad razonable.

Un comentarista preguntó dónde en el estándar dice que el char debe tener al menos 8 bits. Está en la sección 5.2.4.2.1 . Esta sección define CHAR_BIT , el número de bits en la entidad direccionable más pequeña, y tiene un valor predeterminado de 8. También dice:

Sus valores definidos por la implementación serán iguales o mayores en magnitud (valor absoluto) que los mostrados, con el mismo signo.

Por lo tanto, cualquier número igual a 8 o superior es adecuado para la sustitución por una implementación en CHAR_BIT .


Los lenguajes de programación C y C ++, por ejemplo, definen byte como "unidad direccionable de datos lo suficientemente grande como para contener cualquier miembro del conjunto de caracteres básicos del entorno de ejecución" (cláusula 3.6 del estándar C). Dado que el tipo de datos integrales C char debe contener al menos 8 bits (cláusula 5.2.4.2.1), un byte en C es al menos capaz de contener 256 valores diferentes. Varias implementaciones de C y C ++ definen un byte como 8, 9, 16, 32 o 36 bits

Citado de http://en.wikipedia.org/wiki/Byte#History

Sin embargo, no estoy seguro acerca de otros lenguajes.

http://en.wikipedia.org/wiki/IBM_7030_Stretch#Data_Formats

Define un byte en esa máquina para que sea de longitud variable


Algunos de los cuales estoy al tanto

  • DEC PDP-10: variable, pero con mayor frecuencia caracteres de 7 bits empaquetados 5 por palabra de 36 bits, o bien caracteres de 9 bits, 4 por palabra
  • Cuadros principales de control de datos (CDC-6400, 6500, 6600, 7600, Cyber ​​170, Cyber ​​176, etc.) Caracteres de 6 bits, empaquetados 10 por palabra de 60 bits.
  • Unisys mainframes: 9 bits / byte
  • Windows CE: simplemente no admite el tipo `char` en absoluto; requiere wchar_t de 16 bits en su lugar

Ints solía ser de 16 bits (pdp11, etc.). Ir a arquitecturas de 32 bits fue difícil. La gente está mejorando: casi nadie asume que un puntero encajará en algo más (¿no es así?). O archivo de compensaciones, o marcas de tiempo, o ...

Los personajes de 8 bits ya son algo anacrónicos. Ya necesitamos 32 bits para contener todos los conjuntos de caracteres del mundo.


La familia DEC PDP-8 tenía una palabra de 12 bits, aunque generalmente usaba ASCII de 8 bits para la salida (principalmente en un Teletipo). Sin embargo, también había un código de carácter de 6 BITS que le permitía codificar 2 caracteres en una sola palabra de 12 bits.


Las máquinas con arquitecturas de 36 bits tienen bytes de 9 bits. Según Wikipedia, las máquinas con arquitecturas de 36 bits incluyen:

  • Digital Equipment Corporation PDP-6/10
  • IBM 701/704/709/7090/7094
  • UNIVAC 1103 / 1103A / 1105/1100/2200,

Muchos chips DSP tienen caracteres de 16 o 32 bits. TI rutinariamente hace tales chips, por ejemplo .


No hay tal cosa como un código completamente portátil. :-)

Sí, puede haber varios tamaños de bytes / caracteres. Sí, puede haber implementaciones C / C ++ para plataformas con valores altamente inusuales de CHAR_BIT y UCHAR_MAX . Sí, a veces es posible escribir código que no depende del tamaño de char.

Sin embargo, casi cualquier código real no es independiente. Por ejemplo, puede escribir un código que envíe mensajes binarios a la red (el protocolo no es importante). Puede definir estructuras que contengan campos necesarios. Entonces debes serializarlo. La copia binaria de una estructura en un búfer de salida no es portátil: generalmente no conoce ni el orden de bytes para la plataforma ni la alineación de los miembros de la estructura, por lo que la estructura solo contiene los datos, pero no describe la forma en que los datos deberían ser serializados. .

De acuerdo. Puede realizar transformaciones de orden de bytes y mover los miembros de la estructura (por ejemplo, uint32_t o similar) utilizando memcpy en el búfer. ¿Por qué memcpy ? Porque hay muchas plataformas en las que no es posible escribir 32 bits (16 bits, 64 bits, no hay diferencia) cuando la dirección de destino no está alineada correctamente.

Entonces, ya ha hecho mucho para lograr la portabilidad.

Y ahora la pregunta final. Tenemos un buffer Sus datos se envían a la red TCP / IP. Tal red asume bytes de 8 bits. La pregunta es: ¿de qué tipo debe ser el buffer? Si tus caracteres son de 9 bits? Si son de 16 bits? 24? ¿Tal vez cada char corresponde a un byte de 8 bits enviado a la red, y solo se utilizan 8 bits? ¿O tal vez múltiples bytes de red están empaquetados en caracteres de 24/16/9 bits? Esa es una pregunta, y es difícil creer que haya una sola respuesta que se ajuste a todos los casos. Muchas cosas dependen de la implementación del socket para la plataforma objetivo.

Entonces, de lo que estoy hablando. Por lo general, el código puede ser relativamente fácil de transportar en cierta medida . Es muy importante hacerlo si espera usar el código en diferentes plataformas. Sin embargo, mejorar la portabilidad más allá de esa medida es algo que requiere mucho esfuerzo y a menudo da muy poco , ya que el código real casi siempre depende de otro código (implementación de socket en el ejemplo anterior). Estoy seguro de que para cerca del 90% de la capacidad del código para trabajar en plataformas con bytes distintos a 8 bits es casi inútil, ya que usa un entorno que está vinculado a 8 bits. Simplemente verifique el tamaño del byte y realice la aserción del tiempo de compilación. Seguramente tendrá que volver a escribir mucho para una plataforma altamente inusual.

Pero si su código es altamente "independiente", ¿por qué no? Puede escribirlo de forma que permita diferentes tamaños de bytes.


Parece que todavía puede comprar un IM6100 (es decir, un PDP-8 en un chip) de un almacén. Esa es una arquitectura de 12 bits.


Por un lado, los caracteres Unicode son más largos que 8 bits. Como alguien mencionó anteriormente, la especificación C define tipos de datos por sus tamaños mínimos. Use sizeof y los valores en limits.h si desea interrogar sus tipos de datos y descubrir exactamente qué tamaño tienen para su configuración y arquitectura.

Por esta razón, trato de mantener los tipos de datos como uint16_t cuando necesito un tipo de datos de una longitud de bit determinada.

Editar: Lo siento, inicialmente leí mal su pregunta.

La especificación C dice que un objeto char es "lo suficientemente grande como para almacenar cualquier miembro del conjunto de caracteres de ejecución". limits.h enumera un tamaño mínimo de 8 bits, pero la definición deja el tamaño máximo de un char abierto.

Por lo tanto, el char es al menos tan largo como el carácter más grande del conjunto de ejecución de su arquitectura (por lo general redondeado al límite más cercano de 8 bits). Si su arquitectura tiene códigos de operación más largos, su tamaño de char puede ser más largo.

Históricamente, el código de operación de la plataforma x86 era de un byte de longitud, por lo que char era inicialmente un valor de 8 bits. Las plataformas x86 actuales admiten códigos de operación más largos que un byte, pero el char se mantiene en 8 bits de longitud, ya que eso es a lo que los programadores (y los grandes volúmenes del código x86 existente) están condicionados.

Cuando piense en soporte multiplataforma, aproveche los tipos definidos en stdint.h . Si usa (por ejemplo) un uint16_t, puede estar seguro de que este valor es un valor de 16 bits sin firmar en cualquier arquitectura, ya sea que ese valor de 16 bits corresponda a un char , short , int u otra cosa. La mayoría del trabajo duro ya lo han hecho las personas que escribieron tus compiladores / bibliotecas estándar.

Si necesita saber el tamaño exacto de un char porque está haciendo alguna manipulación de hardware de bajo nivel que lo requiera, normalmente uso un tipo de datos que sea lo suficientemente grande como para contener un char en todas las plataformas admitidas (normalmente 16 bits es suficiente) y ejecuta el valor a través de una rutina convert_to_machine_char cuando necesito la representación exacta de la máquina. De esta forma, el código específico de la plataforma se limita a la función de interfaz y la mayoría de las veces puedo usar un uint16_t normal.


char también es de 16 bits en los DSP de Texas Instruments C54x, que apareció, por ejemplo, en OMAP2. Hay otros DSP disponibles con 16 y 32 bit char . Creo que incluso escuché acerca de un DSP de 24 bits, pero no recuerdo qué, así que tal vez lo imaginé.

Otra consideración es que POSIX ordena CHAR_BIT == 8 . Entonces, si estás usando POSIX, puedes asumirlo. Si más adelante alguien necesita portar su código a una implementación cercana de POSIX, tiene las funciones que usa pero un tamaño diferente, es su mala suerte.

En general, sin embargo, creo que es casi siempre más fácil evitar el problema que pensar en ello. Simplemente escriba CHAR_BIT . Si quiere un tipo exacto de 8 bits, use int8_t . Su código no compilará ruidosamente las implementaciones que no proporcionan uno, en lugar de usar silenciosamente un tamaño que no esperaba. Por lo menos, si toco un caso en el que tengo una buena razón para suponerlo, lo afirmaré.