En C / C ++, ¿para qué unsigned charse utiliza? ¿Cómo es diferente de un regular char?
En C ++, hay tres tipos de caracteres distintos :
charsigned charunsigned charSi está utilizando tipos de caracteres para el texto , use el no calificado char:
'a'o '0'."abcde"También funciona como un valor numérico, pero no se especifica si ese valor se trata como con signo o sin signo. Tenga cuidado con las comparaciones de caracteres a través de las desigualdades, aunque si se limita a ASCII (0-127) está a salvo.
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. sizeof (char)se requiere que sea 1 (es decir, un byte), pero un byte podría ser, en teoría, por ejemplo, 32 bits. sizeofseguiría informando su tamaño como1 , lo que significa que podría tener sizeof (char) == sizeof (long) == 1.
sizeofporque no es una función sino un operador. Es incluso mejor estilo omitir el paréntesis cuando se toma el tamaño de una variable.sizeof *posizeof (int). Esto deja en claro rápidamente si se aplica a un tipo o variable. Del mismo modo, también es redundante poner paréntesis despuésreturn. No es una función.char: es el tipo de literales de caracteres como'a'o'0'". es cierto en C ++ pero no en C. En C,'a'es unint.Esto depende de la implementación, ya que el estándar C NO define la firma de
char. Dependiendo de la plataforma, char puede sersignedounsigned, por lo que debe solicitar explícitamentesigned charounsigned charsi su implementación depende de ello. Solo úselocharsi tiene la intención de representar caracteres de cadenas, ya que esto coincidirá con lo que su plataforma pone en la cadena.La diferencia entre
signed charyunsigned chares como era de esperar. En la mayoría de las plataformas,signed charhabrá un número de complemento de dos de 8 bits que va de-128a127, yunsigned charserá un entero sin signo de 8 bits (0a255). Tenga en cuenta que el estándar NO requiere que loschartipos tengan 8 bits, solo esesizeof(char)retorno1. Puede obtener el número de bits en un char conCHAR_BITinlimits.h. Sin8embargo, hay pocas plataformas, si es que hay alguna, en las que esto sea algo diferente .Hay un buen resumen de este problema aquí .
Como otros han mencionado desde que publiqué esto, es mejor que uses
int8_tyuint8_tsi realmente quieres representar números enteros pequeños.fuente
CHAR_BITse requiere que tenga al menos 8 bits según el estándar.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 charparticipan en la determinación del valor de cualquier objeto char sin firmar. En segundo lugar,unsigned charse declara explícitamente sin firmar.Ahora, tuve una discusión con alguien sobre lo que sucede cuando convierte el valor
-1de tipo int aunsigned char. Rechazó la idea de que el resultadounsigned chartiene todos sus bits establecidos en 1, porque estaba preocupado por la representación de signos. Pero no tiene que hacerlo. Inmediatamente después de esta regla, la conversión hace lo que se pretende:Esa es una descripción matemática. C ++ lo describe en términos de cálculo de módulo, que cede a la misma regla. De todos modos, lo que no está garantizado es que todos los bits en el entero
-1sean uno antes de la conversión. Entonces, ¿qué tenemos para poder afirmar que el resultadounsigned chartiene todos susCHAR_BITbits convertidos en 1?UCHAR_MAX+1a-1rendirá un valor en el rango, a saber,UCHAR_MAXEso es suficiente, en realidad! Así que cada vez que quieras tener uno
unsigned charcon todos sus bits, lo hacesTambién se deduce que una conversión no es solo truncar bits de orden superior. El evento afortunado para el complemento de dos es que es solo un truncamiento allí, pero lo mismo no es necesariamente cierto para otras representaciones de signos.
fuente
UCHAR_MAX?(unsigned type)-1es una especie de idioma.~0no lo esint x = 1234ychar *y = &x. Representación binaria de1234is00000000 00000000 00000100 11010010. Mi máquina es little endian, por lo que la invierte y la almacena en memoria.11010010 00000100 00000000 00000000LSB es lo primero. Ahora parte principal. Si usoprintf("%d" , *p).printfleerá el primer byte11010010solo el resultado es-46pero11010010es210así, ¿por qué se imprime-46? Estoy realmente confundido, supongo que una promoción de char a entero está haciendo algo, pero no lo sé.Como, por ejemplo, usos de caracteres sin firmar :
unsigned charA menudo se usa 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 unounsigned char. Como losunsigned charvalores caen en el rango [0,255], los valores generalmente se interpretan como:Entonces terminaría con rojo RGB como (255,0,0) -> (100% rojo, 0% verde, 0% azul).
¿Por qué no usar a
signed char? El cambio aritmético y de bits se vuelve problemático. Como ya se explicó,signed charel rango de a se desplaza esencialmente por -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 tiene problemas cuando los valores de los componentes de color son negativos. El rojo (255, 0, 0) promedia a (85, 85, 85) cuando se usa launsigned chararitmética. Sin embargo, si los valores fueransigned chars (127, -128, -128), terminaríamos con (-99, -99, -99), que sería (29, 29, 29) en nuestrounsigned charespacio, lo cual es incorrecto .fuente
Si desea utilizar un carácter como un entero pequeño, la forma más segura de hacerlo es con los tipos
int8_tyuint8_t.fuente
int8_tyuint8_tson opcionales y no están definidos en arquitecturas donde el tamaño del byte no es exactamente de 8 bits. Por el contrario,signed charyunsigned charsiempre están disponibles y garantizados para contener al menos 8 bits. Puede ser una forma común pero no la más segura .signed charyunsigned char? ¿O recomendaría una mejor alternativa "más segura" en ese caso particular? Por ejemplo, para quedarse con los tipos enteros "reales"signed inty en suunsigned intlugar por alguna razón?signed charyunsigned chares portátil para todas las implementaciones conformes y ahorrará espacio de almacenamiento, pero puede causar un aumento en el tamaño del código. En algunos casos, se ahorraría más espacio de almacenamiento al almacenar valores pequeños en campos de bits o bits individuales de tipos enteros regulares. No hay una respuesta absoluta a esta pregunta, la pertinencia de este enfoque depende del caso específico en cuestión. Y esta respuesta no aborda la pregunta de todos modos.unsigned charsolo toma valores positivos ... como 0 a 255donde como
signed chartoma valores positivos y negativos ... como -128 a +127fuente
charyunsigned charno se garantiza que sean de 8 bits en todas las plataformas; se garantiza que serán de 8 bits o más. Algunas plataformas tienen bytes de 9 bits, 32 bits o 64 bits . Sin embargo, las plataformas más comunes en la actualidad (Windows, Mac, Linux x86, etc.) tienen bytes de 8 bits.fuente
signed chartiene un rango de -128 a 127;unsigned chartiene rango de 0 a 255.charserá equivalente a char firmado o no firmado, dependiendo del compilador, pero es un tipo distinto.Si está utilizando cadenas de estilo C, solo utilícelas
char. Si necesita usar caracteres para aritmética (bastante raro), especifique con o sin signo explícitamente para la portabilidad.fuente
Un
unsigned chares un valor de byte sin signo (0 a 255). Puede estar pensandocharen términos de ser un "personaje", pero en realidad es un valor numérico. El regularcharestá firmado, por lo que tiene 128 valores, y estos valores se asignan a caracteres mediante codificación ASCII. Pero en cualquier caso, lo que está almacenando en la memoria es un valor de byte.fuente
En términos de valores directos, se utiliza un carácter normal cuando se sabe que los valores están entre
CHAR_MINyCHAR_MAXmientras que un carácter sin signo proporciona el doble del rango en el extremo positivo. Por ejemplo, siCHAR_BITes 8, el rango de regularcharsolo se garantiza que sea [0, 127] (porque puede estar firmado o no) mientrasunsigned charque será [0, 255] ysigned charserá [-127, 127].En términos de para qué se utiliza, los estándares permiten que los objetos de POD (datos antiguos simples) se conviertan directamente en una matriz de caracteres sin signo. Esto le permite examinar la representación y los patrones de bits del objeto. La misma garantía de juego seguro no existe para char o char firmado.
fuente
unsigned char, no una matriz específicamente, y cualquier "conversión" solo se define formalmente copiando del objeto a una matriz real declarada deunsigned chary luego inspeccionando el último. No está claro si el OR se puede reinterpretar directamente como una matriz de este tipo, con las tolerancias para la aritmética del puntero que implicaría, es decir, si la "secuencia"=="matriz" en este uso. Hay un problema central # 1701 abierto con la esperanza de aclarar esto. Afortunadamente, ya que esta ambigüedad realmente me está molestando recientemente.unsigned charde la OR y luego continuar usando++ptrdesde allí para leer cada byte ... pero AFAICT, no se define específicamente como permitido, por lo que estamos Dejó inferir que está "probablemente bien" en muchos otros pasajes (y en muchos sentidos, la mera existencia dememcpy) en el Estándar, similar a un rompecabezas. Lo cual no es ideal. Bueno, tal vez la redacción mejore eventualmente. Aquí está el problema de CWG que mencioné pero que no tenía espacio para vincular: open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1701unsigned chares el corazón de todos los trucos. En casi TODO el compilador para TODAS las plataformas, ununsigned chares simplemente un byte y un entero sin signo de (generalmente) 8 bits que pueden tratarse como un entero pequeño o un paquete de bits.En adicción, como alguien más ha dicho, el estándar no define el signo de un personaje. por lo que tiene 3 distintos
chartipos:char,signed char,unsigned char.fuente
Si te gusta usar varios tipos de longitud y de signo específico, usted es probablemente mejor con
uint8_t,int8_t,uint16_t, etc, simplemente porque hacen exactamente lo que dicen.fuente
Algunos buscadores en Google encontraron esto , 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 indicadores para que se pasen a una función, como se hace a menudo en la API de Windows).
fuente
Un personaje sin signo utiliza el bit que está reservado para el signo de un personaje normal como otro número. Esto cambia el rango a [0 - 255] en lugar de [-128 - 127].
Generalmente, los caracteres sin signo se usan cuando no desea una señal. Esto marcará una diferencia al hacer cosas como cambiar bits (shift extiende el signo) y otras cosas cuando se trata de un carácter como un byte en lugar de usarlo como un número.
fuente
unsigned charsolo toma valores positivos: 0 a 255, mientras quesigned chartoma valores positivos y negativos: -128 a +127.fuente
citado del libro "the c programa laugage":
El calificador
signedounsignedse puede aplicar a char o cualquier número entero. los números sin signo son siempre 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. Entonces, 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 una máquina complementaria de dos). Si los caracteres simples son con signo o sin signo es máquina independientes, pero los caracteres imprimibles son siempre positivos.fuente
signed charyunsigned charambos representan 1byte, pero tienen diferentes rangos.En
signed charsi tenemos en cuentachar letter = 'A', 'A' es representar binaria de 65 enASCII/Unicode, 65 Si se puede almacenar, -65 también se pueden almacenar. No hay valores binarios negativosASCII/Unicodeallí para no tener que preocuparse por los valores negativos.Ejemplo
Salida -:
fuente