¿Qué plataformas tienen algo más que char de 8 bits?

136

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

Parece que 8 bits chares casi universal. Pensé que para las plataformas convencionales, es necesario tener un bit de 8 bits charpara garantizar su viabilidad en el mercado.

Tanto ahora como históricamente, ¿qué plataformas usan una charque no sea de 8 bits y por qué diferirían de los 8 bits "normales"?

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

En el pasado me he encontrado con algunos DSP de dispositivos analógicos para los cuales chares de 16 bits. Los DSP son un poco de arquitectura de nicho, supongo. (Por otra parte, en ese momento, el ensamblador codificado a mano venció fácilmente lo que los compiladores de C disponibles podían hacer, por lo que realmente no obtuve mucha experiencia con C en esa plataforma).

Craig McQueen
fuente
9
La serie Cyber ​​de CDC tenía una codificación de 6/12 bits. Los personajes más populares eran 6 bits. Los caracteres restantes utilizaron 12 bits.
Thomas Matthews
2
El PDP-11 lo clavó. La noción de que un personaje puede ser codificado en un personaje es muy obsoleto.
Hans Passant el
77
"El PDP-11 lo logró" - ¿Quiere decir que C se implementó por primera vez para el PDP-11 con bytes de 8 bits? Pero C se implementó luego para máquinas Honeywell con bytes de 9 bits. Ver K&R versión 1. Además, la pregunta se hizo sobre char (es decir, byte) no sobre el carácter (uno o más bytes que codifican algo que no se le preguntó).
programador de Windows
66
DEC-10 y DEC-20 tenían palabras de 36 bits. Cinco caracteres ASCII de 7 bits por palabra eran bastante comunes. También se utilizaron seis caracteres de 6 bits.
David R Tribble
3
@CraigMcQueen: Si no recuerdo mal, CodeVision para los microcontroladores Atmel le permite a uno elegir el tamaño de char
vsz

Respuestas:

80

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

Otra consideración es que los mandatos POSIX CHAR_BIT == 8. Entonces, si está utilizando POSIX, puede asumirlo. Si alguien más tarde necesita portar su código a una implementación cercana de POSIX, resulta que tiene las funciones que usa pero un tamaño diferente char, esa es su mala suerte.

Sin embargo, en general, creo que casi siempre es más fácil solucionar el problema que pensarlo. Solo escribe CHAR_BIT. Si desea un tipo exacto de 8 bits, use int8_t. Su código no se compilará ruidosamente en implementaciones que no proporcionan uno, en lugar de usar en silencio un tamaño que no esperaba. Por lo menos, si llego a un caso en el que tengo una buena razón para asumirlo, entonces lo afirmaría.

Steve Jessop
fuente
2
Los DSP TI C62xx y C64xx también tienen caracteres de 16 bits. (uint8_t no está definido en esa plataforma.)
myron-semack
77
Muchos DSP para procesamiento de audio son máquinas de 24 bits; los DSP de BelaSigna de On Semi (después de que compraron AMI Semi); los DSP56K / Symphony Audio DSP de Freescale (después de que se separaron de Motorola).
David Cary
2
@msemack C64xx tiene hardware para 8/16/32/40 y 8bit char
user3528438
44
En lugar de assert()(si eso es lo que quisiste decir), usaría #if CHAR_BIT != 8... #error "I require CHAR_BIT == 8"...#endif
Keith Thompson el
1
@KeithThompson ¿Hay alguna razón para no usar static_assert()?
Qix - MONICA FUE MALTRATADA
37

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

No es tanto que "valga la pena considerar" algo, sino 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 supone que los bytes tienen exactamente 8 bits, está violando el estándar.

Esto puede parecer una tontería ahora - " por supuesto todos los bytes tienen 8 bits!" 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 suponían que un retraso de temporización de CPU sin operación particular que tomaba un número fijo de ciclos tomaría una cantidad fija de tiempo de reloj, porque la mayoría de las CPU de consumo tenían una potencia aproximadamente equivalente. Desafortunadamente, las computadoras se hicieron más rápidas muy 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 usaran la técnica de retardo de tiempo pudieran jugarse a una velocidad razonable.


Un comentarista preguntó en qué parte del estándar dice que char debe tener al menos 8 bits. Está en la sección 5.2.4.2.1 . Esta sección define CHAR_BITel 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) a 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.

John Feminella
fuente
66
No he visto un botón Turbo en al menos 20 años, ¿realmente crees que está relacionado con la pregunta?
Mark Ransom
29
@ Mark Ransom: Ese es el punto. Los desarrolladores a menudo confían en suposiciones que parecen ser ciertas en este momento, pero que son mucho más inestables de lo que parecen inicialmente. (¡No puedo contar la cantidad de veces que he cometido ese error!) El botón Turbo debería ser un recordatorio doloroso de no hacer suposiciones innecesarias, y ciertamente no hacer suposiciones que no están garantizadas por un estándar de idioma como si fueran hechos inmutables
John Feminella
1
¿Podría señalar colocar en C ++ Standard que dice que el bye tiene al menos 8 bits? Es una creencia común, sin embargo, personalmente no pude encontrarlo en el Estándar. Lo único que encontré en Standard es qué caracteres deben ser representables charya que hay más de 64 de ellos pero menos de 128, por lo que 7 bits serían suficientes.
Adam Badura
66
La Sección 18.2.2 invoca el estándar C para ello. En el estándar C es la sección 7.10 y luego la sección 5.4.2.4.1. Página 22 en el estándar C.
Programador de Windows el
2
Entonces, otras respuestas y comentarios mencionan máquinas con bytes de 5, 6 y 7 bits. ¿Eso significa que no puede ejecutar un programa C en esa máquina que cumpla con el estándar?
Jerry Jeremiah
34

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,
R Samuel Klatchko
fuente
77
También máquinas Honeywell, como quizás la segunda máquina donde se implementó C. Ver K&R versión 1.
Programador de Windows
55
En realidad, el 10-Dic también tuvo caracteres de 6 bits - se puede empacar 6 de estos en una palabra de 36 bits (ex-dic-10 programador de conversación)
2
El DEC-20 utilizó cinco caracteres ASCII de 7 bits por palabra de 36 bits en el TOPS-20 O / S.
David R Tribble
3
Ese chiste se implementó realmente para admitir Unicode en esta arquitectura.
Joshua
9
Me imagino que la razón por la que se usó octal fue porque 3 dígitos octales representan claramente un byte de 9 bits, al igual que usualmente usamos hexadecimal hoy porque dos dígitos hexadecimales representan claramente un byte de 8 bits.
bames53
18

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
  • Mainframes de datos de control (CDC-6400, 6500, 6600, 7600, Cyber ​​170, Cyber ​​176 etc.) caracteres de 6 bits, empaquetados 10 por palabra de 60 bits.
  • Mainframes de Unisys: 9 bits / byte
  • Windows CE: simplemente no admite el tipo `char` en absoluto; en su lugar requiere wchar_t de 16 bits
Jerry Coffin
fuente
2
@ephemient: estoy bastante seguro de que había al menos un compilador de C (pre-estándar) para el PDP-10 / DecSystem 10 / DecSystem 20. Sin embargo, me sorprendería mucho un compilador de C para los mainframes CDC (estaban utilizado principalmente para trabajo numérico, por lo que el compilador Fortran fue lo más importante allí). Estoy bastante seguro de que los otros tienen compiladores de C.
Jerry Coffin
3
¿El compilador de Windows CE realmente no era compatible con el chartipo? Sé que las bibliotecas del sistema solo admiten las versiones de caracteres anchos de las funciones que toman cadenas, y que al menos algunas versiones de WinCE eliminaron las funciones de cadena ANSI como strlen, para evitar que maneje cadenas de caracteres char. ¿Pero realmente no tenía un tipo de char en absoluto? ¿Qué fue sizeof(TCHAR)? ¿Qué tipo regresó malloc? ¿Cómo se byteimplementó el tipo Java ?
Steve Jessop el
10
Windows CE admite char, que es un byte. Vea el comentario de Craig McQueen sobre la respuesta de Richard Pennington. Los bytes se necesitan tanto en Windows CE como en cualquier otro lugar, sin importar el tamaño que tengan en cualquier otro lugar.
Programador de Windows el
2
Hay (¿hubo?) Al menos dos implementaciones de C para el PDP-10: KCC y un puerto de gcc ( pdp10.nocrew.org/gcc ).
Programador
3
El estándar C no permitiría caracteres de 7 bits empaquetados 5 por palabra de 36 bits (como mencionó para el PDP-10), ni permitiría caracteres de 6 bits, como mencionó para los mainframes de Control Data. Ver parashift.com/c++-faq-lite/intrinsic-types.html#faq-26.6
Ken Bloom
15

No existe un código completamente portátil. :-)

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

Sin embargo, casi cualquier código real no es independiente. Por ejemplo, puede estar escribiendo un código que envía mensajes binarios a la red (el protocolo no es importante). Puede definir estructuras que contengan campos necesarios. Entonces tienes que serializarlo. La copia binaria de una estructura en un búfer de salida no es portátil: generalmente no conoce el orden de bytes de 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 deben ser serializados. .

Okay. Puede realizar transformaciones de orden de bytes y mover los miembros de la estructura (p. Ej. uint32_tO similares) utilizando memcpyel búfer. ¿Por qué memcpy? Debido a que hay muchas plataformas donde no es posible escribir 32 bits (16 bits, 64 bits, sin diferencia) cuando la dirección de destino no está alineada correctamente.

Entonces, ya has hecho mucho para lograr la portabilidad.

Y ahora la pregunta final. Tenemos un buffer Los datos se envían a la red TCP / IP. Dicha red asume bytes de 8 bits. La pregunta es: ¿de qué tipo debería ser el búfer? Si tus caracteres son de 9 bits? Si son de 16 bits? 24? ¿Quizás cada carácter 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 de creer que haya una respuesta única que se ajuste a todos los casos. Muchas cosas dependen de la implementación del socket para la plataforma de destino.

Entonces, de lo que estoy hablando. Por lo general, el código puede hacerse relativamente fácil de transportar hasta cierto punto . 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 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 aproximadamente el 90% de la capacidad del código para trabajar en plataformas con bytes distintos de 8 bits es casi inútil, ya que utiliza un entorno vinculado a 8 bits. Simplemente verifique el tamaño del byte y realice la aserción del tiempo de compilación. Seguramente tendrá que reescribir mucho para una plataforma muy inusual.

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

Ellioh
fuente
44
Si se almacena un octeto por unsigned charvalor, no debería haber problemas de portabilidad a menos que el código utilice trucos de alias en lugar de cambios para convertir secuencias de octetos a / desde tipos enteros más grandes. Personalmente, creo que el estándar C debería definir intrínsecos para empacar / desempaquetar enteros de secuencias de tipos más cortos (más típicamente char) almacenando un número fijo de bits garantizados disponibles por elemento (8 por unsigned char, 16 por unsigned shorto 32 por unsigned long).
supercat
9

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

dmckee --- gatito ex moderador
fuente
9

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

Alok Singhal
fuente
5

Los lenguajes de programación C y C ++, por ejemplo, definen byte como "unidad de datos direccionable 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 integral 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. Diversas 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 idiomas.

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

Define un byte en esa máquina como longitud variable

petantik
fuente
1
"No estoy seguro acerca de otros idiomas", históricamente, la mayoría de los idiomas permitieron que la arquitectura de la máquina definiera su propio tamaño de bytes. En realidad, históricamente también lo hizo C, hasta que el estándar estableció un límite inferior en 8.
Programador de Windows
4

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

PrgTrdr
fuente
3

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

Por esta razón, trato de mantener los tipos de datos como uint16_tcuando necesito un tipo de datos de una longitud de bits particular.

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

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

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

Históricamente, el código de operación de la plataforma x86 tenía un byte de largo, así que char lo que inicialmente era un valor de 8 bits. Las plataformas x86 actuales admiten códigos de operación de más de un byte, pero charse mantienen a 8 bits de longitud ya que a eso están condicionados los programadores (y los grandes volúmenes de código x86 existente).

Cuando piense en el 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 signo en cualquier arquitectura, ya sea que ese valor de 16 bits corresponda a a char,short , int, o alguna otra cosa. La mayoría del trabajo duro ya lo han hecho las personas que escribieron su compilador / bibliotecas estándar.

Si necesita saber el tamaño exacto de a charporque está haciendo una manipulación de hardware de bajo nivel que lo requiere, normalmente utilizo un tipo de datos que es lo suficientemente grande como para contener un charen todas las plataformas compatibles (generalmente 16 bits es suficiente) y ejecutar el valor a través de una convert_to_machine_charrutina cuando necesito la representación exacta de la máquina. De esa manera, 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 normal uint16_t.

bta
fuente
2
La pregunta no se refería a los personajes (ya sea Unicode o no). Preguntó sobre char, que es un byte.
Programador de Windows el
1
Además, el conjunto de caracteres de ejecución no tiene nada que ver con los códigos de operación, es el conjunto de caracteres utilizado en la ejecución, piense en compiladores cruzados.
ninjalj
"Históricamente, el código de operación de la plataforma x86 tenía un byte de largo": qué dulce. Históricamente , C se desarrolló en un PDP-11 (1972), mucho antes de que se inventara x86 (1978).
Martin Bonner apoya a Monica el
3

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

los números mágicos ocurren, por ejemplo, cuando se cambia;

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

espero que su implementación los defina :)

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

Otro problema indirecto es decir que tiene:

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 contenía "indicadores de bit" y cada uchar solo tenía 2 bits o indicadores "significativos" que estaba usando actualmente, y solo los organizó en 3 uchars para "claridad", entonces podría ser relativamente "más derrochador", por ejemplo, en una plataforma con uchars de 24 bits .....

nada que los campos de bits no puedan resolver, pero tienen otras cosas a tener en cuenta ...

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

tal vez no sea un ejemplo real, pero cosas como esta me "mordieron" al portar / jugar con algún código .....

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

así que las cosas todavía pueden estar "rotas" o en este caso "desperdiciar mucha memoria muy rápidamente" debido a la suposición de que un uchar es "no muy derrochador" en una plataforma, en relación con la RAM disponible, que en otra plataforma ... ..

el problema puede ser más prominente, por ejemplo, para ints también, u otros tipos, por ejemplo, tiene una estructura que necesita 15 bits, por lo que la pega en un int, pero en alguna otra plataforma un int es de 48 bits o lo que sea ... .

"normalmente" puede dividirlo en 2 uchars, pero, por ejemplo, con un uchar de 24 bits solo necesitaría uno .....

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

depende de cómo estás accediendo a esos bits aunque :)

por lo tanto, puede haber "fallas de diseño" que críen su cabeza ... incluso si el código aún funciona / funciona bien, independientemente del tamaño de un uchar o uint ...

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

Espero que esto tenga sentido :)

dd ee
fuente
1
...¿qué? ¿Por qué crees que enumes probable que sea más pequeño que otros tipos nativos? ¿Sabe que el valor predeterminado es el mismo almacenamiento que int? "usted tiene algún tipo de estructura que necesita 15 bits, por lo que se pega en un int, sino en alguna otra plataforma de un int es de 48 bits o lo que sea ....." - así #include <cstdint>y lo convierten en una int16_tde las mejores posibilidades de minimizar el uso de bits . Realmente no estoy seguro de lo que pensaste que estabas diciendo entre todas esas elipses.
underscore_d
1

las entradas solían ser de 16 bits (pdp11, etc.). Ir a arquitecturas de 32 bits fue difícil. La gente está mejorando: casi nadie supone que un puntero cabe en mucho tiempo (¿no es cierto?). O compensaciones de archivos, o marcas de tiempo, o ...

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

Richard Pennington
fuente
2
Cierto. El nombre chares un poco pintoresco ahora en días Unicode. Me interesan más las unidades de 8 bits (octetos) cuando se trata de datos binarios, por ejemplo, almacenamiento de archivos, comunicaciones de red. uint8_tEs más útil.
Craig McQueen
3
Unicode nunca necesitó 32 bits completos, en realidad. Originalmente planearon 31 (ver el trabajo original de UTF-8), pero ahora están contentos con solo 21 bits . Probablemente se dieron cuenta de que ya no podrían imprimir el libro si realmente necesitaran los 31 bits: P
me22
2
@ me22, Unicode originalmente planeado para 16 bits. "Los caracteres Unicode son consistentemente de 16 bits de ancho, independientemente del idioma ..." Unicode 1.0.0. unicode.org/versions/Unicode1.0.0/ch01.pdf .
Shannon Severance
1
ISO 10646 tenía originalmente 31 bits, y Unicode se fusionó con ISO 10646, por lo que podría ser descuidado decir que Unicode tenía 31 bits, pero no es realmente falso. Tenga en cuenta que ya no imprimen las tablas de códigos completas.
prosfilaes