it-swarm-es.tech

¿Qué es un char sin firmar?

En C/C++, ¿para qué se utiliza un unsigned char? ¿En qué se diferencia de una char regular?

427
Landon Kuhn

En C++, hay tres distintos tipos de caracteres:

  • char
  • signed char
  • unsigned char

Si está utilizando tipos de caracteres para text , use la char no calificada:

  • es el tipo de caracteres literales como 'a' o '0'.
  • es el tipo que compone las cadenas C como "abcde"

También funciona como un valor numérico, pero no se especifica si ese valor se trata como firmado o no firmado. Tenga cuidado con las comparaciones de caracteres a través de las desigualdades, aunque si se limita a ASCII (0-127), está casi seguro.

Si está utilizando tipos de caracteres como números , use:

  • signed char, que le da al menos el rango de -127 a 127. (-128 a 127 es común)
  • unsigned char, que le da al menos el rango de 0 a 255.

"Al menos", porque el estándar C++ solo proporciona el rango mínimo de valores que cada tipo numérico debe cubrir. Se requiere que sizeof (char) sea 1 (es decir, un byte), pero en teoría un byte podría ser, por ejemplo, de 32 bits.sizeof AÚN SE INFORMARÍA DE SU TAMAÑO COMO 1- lo que significa que podría tener sizeof (char) == sizeof (long) == 1.

509
Fruny

Esto depende de la implementación, ya que el estándar C NO define la firma de char. Dependiendo de la plataforma, char puede ser signed o unsigned, por lo que debe solicitar explícitamente signed char o unsigned char si su implementación depende de ello. Simplemente use char si pretende representar caracteres de cadenas, ya que esto coincidirá con lo que su plataforma pone en la cadena.

La diferencia entre signed char y unsigned char es la que usted esperaría. En la mayoría de las plataformas, signed char será un número de complemento de dos bits de 8 bits que va desde -128 a 127, y unsigned char será un entero sin signo de 8 bits (0 a 255). Tenga en cuenta que el estándar NO requiere que los tipos char tengan 8 bits, solo que sizeof(char) return 1. Puede obtener la cantidad de bits en un char con CHAR_BIT en limits.h. Sin embargo, existen pocas plataformas, si es que existen, en las que esto sea algo distinto de 8, sin embargo.

Hay un buen resumen de este problema aquí .

Como otros han mencionado desde que publiqué esto, es mejor usar int8_t y uint8_t si realmente quieres representar a los enteros pequeños.

79
Todd Gamblin

Debido a que siento que es realmente necesario, solo quiero establecer algunas reglas de C y C++ (son las mismas en este sentido). Primero, todos los bits de unsigned char participan en la determinación del valor de cualquier objeto char sin signo. En segundo lugar, unsigned char se declara explícitamente sin firmar.

Ahora, tuve una discusión con alguien sobre lo que sucede cuando convierte el valor -1 de tipo int a unsigned char. Rechazó la idea de que el unsigned char resultante tiene todos sus bits establecidos en 1, porque estaba preocupado por la representación de signos. Pero él no tiene que hacerlo. Inmediatamente después de esta regla, la conversión hace lo que se pretende:

Si el nuevo tipo no está firmado, el valor se convierte sumando o restando repetidamente uno más que el valor máximo que se puede representar en el nuevo tipo hasta que el valor esté en el rango del nuevo tipo. (6.3.1.3p2 en un borrador de C99)

Esa es una descripción matemática. C++ lo describe en términos de cálculo de módulo, que da como resultado la misma regla. De todos modos, lo que está no garantizado es que todos los bits en el entero -1 son uno antes de la conversión. Entonces, ¿qué tenemos para que podamos afirmar que el unsigned char resultante tiene todos sus CHAR_BIT bits convertidos a 1?

  1. Todos los bits participan en la determinación de su valor, es decir, no se producen bits de relleno en el objeto.
  2. Agregar solo una vez UCHAR_MAX+1 a -1 producirá un valor dentro del rango, a saber, UCHAR_MAX

Eso es suficiente, en realidad! Así que cuando quieras tener un unsigned char que tenga todos sus bits uno, lo haces

unsigned char c = (unsigned char)-1;

También se deduce que una conversión es no simplemente truncando bits de orden superior. El evento afortunado para complemento de dos es que es solo un truncamiento allí, pero lo mismo no es necesariamente cierto para otras representaciones de signos.

35

Como por ejemplo los usos de unsigned char:

unsigned char se usa a menudo en gráficos de computadora, que muy a menudo (aunque no siempre) asigna un solo byte a cada componente de color. Es común ver un color RGB (o RGBA) representado como 24 (o 32) bits, cada uno un carácter sin signo. Dado que los valores caracteres sin signo están en el rango [0,255], los valores se interpretan normalmente como:

  • 0 significa una falta total de un componente de color dado.
  • 255 significa 100% de un pigmento de color dado.

Así que terminarías con rojo RGB como (255,0,0) -> (100% rojo, 0% verde, 0% azul).

¿Por qué no usar un carácter firmado? La aritmética y el cambio de bits se vuelve problemático. Como ya se explicó, el rango de un carácter firmado se desplaza esencialmente en -128. Un método muy simple e ingenuo (en su mayoría no utilizado) para convertir RGB a escala de grises es promediar los tres componentes de color, pero esto genera problemas cuando los valores de los componentes de color son negativos. El rojo (255, 0, 0) promedia a (85, 85, 85) cuando se usa carácter sin signo aritmética. Sin embargo, si los valores fueran carácter firmado s (127, -128, -128), terminaríamos con (-99, -99, -99), que sería (29, 29, 29) en nuestro unsigned char espacio, que es incorrecto.

24
Zachary Garrett

Si desea utilizar un carácter como un entero pequeño, la forma más segura de hacerlo es con los tipos int8_t y uint8_t.

12
jbleners

signed char tiene un rango de -128 a 127; unsigned char tiene un rango de 0 a 255.

char será equivalente a char firmado o unsigned, dependiendo del compilador, pero es un tipo distinto.

Si estás usando cadenas de estilo C, solo usa char. Si necesita usar caracteres para la aritmética (bastante raro), especifique firmado o no firmado explícitamente para la portabilidad.

5
James Hopkin

No se garantiza que char y unsigned char sean tipos de 8 bits en todas las plataformas; se garantiza que sean de 8 bits o más. Algunas plataformas tienen bytes de 9, 32 o 64 bits . Sin embargo, las plataformas más comunes en la actualidad (Windows, Mac, Linux x86, etc.) tienen bytes de 8 bits.

5
bk1e

En términos de valores directos, se utiliza un carácter regular cuando se sabe que los valores están entre CHAR_MIN y CHAR_MAX, mientras que un carácter sin signo proporciona el doble del rango en el extremo positivo. Por ejemplo, si CHAR_BIT es 8, el rango de char regular solo se garantiza que sea [0, 127] (porque puede estar firmado o no) mientras que unsigned char será [0, 255] y signed char será [-127, 127 ].

En términos de para qué se utiliza, los estándares permiten que los objetos de POD (datos antiguos) se conviertan directamente en una matriz de caracteres sin signo. Esto le permite examinar la representación y los patrones de bits del objeto. No existe la misma garantía de punking de tipo seguro para char o char firmado.

4
Julienne Walker

unsigned char toma solo valores positivos .... como 0 a 255

donde como

signed char toma valores positivos y negativos .... como -128 a +127

4
munna

Un carácter sin signo es un valor de byte (sin signo) (0 a 255). Puede estar pensando en "char" en términos de ser un "personaje" pero en realidad es un valor numérico. El "char" normal está firmado, por lo que tiene 128 valores, y estos valores se asignan a los caracteres usando la codificación ASCII Pero en cualquier caso, lo que está almacenando en la memoria es un valor de byte.

3
Zac Gochenour

Si te gusta usar varios tipos de longitud y firmeza específicas, probablemente estés mejor con uint8_t, int8_t, uint16_t, etc. simplemente porque hacen exactamente lo que dicen.

2
Dark Shikari

Un carácter sin signo utiliza el bit que está reservado para el signo de un carácter regular como otro número. Esto cambia el rango a [0 - 255] en lugar de [-128 - 127].

Generalmente los caracteres sin firmar se usan cuando no quieres un signo. Esto hará una diferencia cuando haga cosas como cambiar los bits (el desplazamiento extiende el signo) y otras cosas cuando se trata de un carácter como un byte en lugar de usarlo como un número.

2
JasonOfEarth

sin firmar char es el corazón de todos los trucos de bits. En casi TODOS los compiladores para TODAS las plataformas, un carácter sin firmar es simplemente un BYTE. Un entero sin signo de (normalmente) 8 bits. que puede tratarse como un pequeño entero o un paquete de bits.

En la adicción, como lo ha dicho otra persona, la norma no define el signo de un personaje. así que tienes 3 tipos distintos de "char": char, signed char, unsigned char.

2
ugasoft

Algunos googleando encontraron this , donde la gente tuvo una discusión sobre esto.

Un carácter sin signo es básicamente un solo byte. Por lo tanto, usaría esto si necesita un byte de datos (por ejemplo, tal vez quiera usarlo para activar y desactivar las marcas y pasarlas a una función, como suele hacerse en la API de Windows).

1
dbrien

los caracteres sin signo solo toman valores positivos: 0 a 255 los caracteres con signo toman valores positivos y negativos: -128 a +127

0
NL628

citado en el libro "the c programación laugage":

El calificador signed o unsigned puede aplicarse a char o cualquier número entero. los números sin signo siempre son positivos o cero, y obedecen las leyes del módulo aritmético 2 ^ n, donde n es el número de bits en el tipo. Así, por ejemplo, si los caracteres son de 8 bits, las variables de caracteres sin signo tienen valores entre 0 y 255, mientras que los caracteres con signo tienen valores entre -128 y 127 (en la máquina del complemento a dos). Si los caracteres simples están firmados o no. -dependientes, pero los caracteres imprimibles son siempre positivos.

0
ZhaoGang