En C / C ++, ¿para qué unsigned char
se utiliza? ¿Cómo es diferente de un regular char
?
En C ++, hay tres tipos de caracteres distintos :
char
signed char
unsigned char
Si 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. sizeof
seguiría informando su tamaño como1
, lo que significa que podría tener sizeof (char) == sizeof (long) == 1
.
sizeof
porque 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 *p
osizeof (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 sersigned
ounsigned
, por lo que debe solicitar explícitamentesigned char
ounsigned char
si su implementación depende de ello. Solo úselochar
si 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 char
yunsigned char
es como era de esperar. En la mayoría de las plataformas,signed char
habrá un número de complemento de dos de 8 bits que va de-128
a127
, yunsigned char
será un entero sin signo de 8 bits (0
a255
). Tenga en cuenta que el estándar NO requiere que loschar
tipos tengan 8 bits, solo esesizeof(char)
retorno1
. Puede obtener el número de bits en un char conCHAR_BIT
inlimits.h
. Sin8
embargo, 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_t
yuint8_t
si realmente quieres representar números enteros pequeños.fuente
CHAR_BIT
se 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 char
participan en la determinación del valor de cualquier objeto char sin firmar. 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 aunsigned char
. Rechazó la idea de que el resultadounsigned char
tiene 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
-1
sean uno antes de la conversión. Entonces, ¿qué tenemos para poder afirmar que el resultadounsigned char
tiene todos susCHAR_BIT
bits convertidos en 1?UCHAR_MAX+1
a-1
rendirá un valor en el rango, a saber,UCHAR_MAX
Eso es suficiente, en realidad! Así que cada vez que quieras tener uno
unsigned char
con 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)-1
es una especie de idioma.~0
no lo esint x = 1234
ychar *y = &x
. Representación binaria de1234
is00000000 00000000 00000100 11010010
. Mi máquina es little endian, por lo que la invierte y la almacena en memoria.11010010 00000100 00000000 00000000
LSB es lo primero. Ahora parte principal. Si usoprintf("%d" , *p)
.printf
leerá el primer byte11010010
solo el resultado es-46
pero11010010
es210
así, ¿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 char
A 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 char
valores 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 char
el 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 char
aritmética. Sin embargo, si los valores fueransigned char
s (127, -128, -128), terminaríamos con (-99, -99, -99), que sería (29, 29, 29) en nuestrounsigned char
espacio, 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_t
yuint8_t
.fuente
int8_t
yuint8_t
son opcionales y no están definidos en arquitecturas donde el tamaño del byte no es exactamente de 8 bits. Por el contrario,signed char
yunsigned char
siempre están disponibles y garantizados para contener al menos 8 bits. Puede ser una forma común pero no la más segura .signed char
yunsigned char
? ¿O recomendaría una mejor alternativa "más segura" en ese caso particular? Por ejemplo, para quedarse con los tipos enteros "reales"signed int
y en suunsigned int
lugar por alguna razón?signed char
yunsigned char
es 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 char
solo toma valores positivos ... como 0 a 255donde como
signed char
toma valores positivos y negativos ... como -128 a +127fuente
char
yunsigned char
no 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 char
tiene un rango de -128 a 127;unsigned char
tiene rango de 0 a 255.char
será 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 char
es un valor de byte sin signo (0 a 255). Puede estar pensandochar
en términos de ser un "personaje", pero en realidad es un valor numérico. El regularchar
está 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_MIN
yCHAR_MAX
mientras que un carácter sin signo proporciona el doble del rango en el extremo positivo. Por ejemplo, siCHAR_BIT
es 8, el rango de regularchar
solo se garantiza que sea [0, 127] (porque puede estar firmado o no) mientrasunsigned char
que será [0, 255] ysigned char
será [-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 char
y 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 char
de la OR y luego continuar usando++ptr
desde 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 char
es el corazón de todos los trucos. En casi TODO el compilador para TODAS las plataformas, ununsigned char
es 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
char
tipos: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 char
solo toma valores positivos: 0 a 255, mientras quesigned char
toma valores positivos y negativos: -128 a +127.fuente
citado del libro "the c programa laugage":
El calificador
signed
ounsigned
se 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 char
yunsigned char
ambos representan 1byte, pero tienen diferentes rangos.En
signed char
si 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/Unicode
allí para no tener que preocuparse por los valores negativos.Ejemplo
Salida -:
fuente