2010-03-26 18 views
10

He leído que C no define si un carácter está firmado o no, y en la página de GCC dice que puede estar firmado en x86 y sin firmar en PowerPPC y ARM.Pregunta de Char C acerca de la codificación firmada/no firmada

Okey, estoy escribiendo un programa con GLIB que define char como gchar (no más que eso, solo una forma de estandarización).

Mi pregunta es, ¿qué hay de UTF-8? Utiliza más de un bloque de memoria?

decir que tengo una cadena char * sin firmar

variable = "Mi cadena con Enconding UTF8 ~> CA";

Véase, si yo declaro mi variable como

sin firmar

voy a tener sólo 127 valores (por lo que mi programa para almacenar más bloques del MEM) o la codificación UTF-8 cambiar a negativo también?

Lo siento si no puedo explicarlo correctamente, pero creo que soy un poco complejo.

NOTA: Gracias por toda responden

No entiendo cómo se interpreta normalmente.

Creo que, como ascii, si tengo una charla firmada y no firmada en mi programa, las cadenas tienen valores diferentes, y eso puede confundir, imagínenlo en utf8.

+0

Si está utilizando una máquina moderna, la chapa sin signo admitirá los valores 0..255. Pero UTF-8 es una codificación multibyte: utiliza 1..4 bytes para cada carácter Unicode. –

+0

Estoy hablando de @Michael Burr dijo. – drigoSkalWalker

Respuesta

1

No realmente, unsigned/signed no especifica cuántos valores puede contener una variable. Especifica cómo están interpretados. Por ejemplo, unsigned char tiene la misma cantidad de valores que signed char, excepto que uno tiene números negativos y el otro no. Todavía son 8 bits (si suponemos que un char contiene 8 bits, no estoy seguro de que lo haga en todas partes).

+1

El estándar C garantiza que un personaje tiene al menos 8 bits; quedan pocas máquinas de caracteres de 9 o 10 bits. –

2

firmado/sin firmar afectan solo a las operaciones aritméticas. si char no está firmado, los valores más altos serán positivos. en caso de firmar, serán negativos. Pero el rango es el mismo todavía.

1

No hace diferencias cuando se utiliza un char * como cadena. La única vez que se firma/no firma la diferencia es si la interpretaría como un número, como en el caso de la aritmética o si la imprimiera como un número entero.

+2

También puede marcar la diferencia si está comparando personajes. Por ejemplo, en el caso UTF8, los caracteres 'bandera' generalmente serán negativos si 'char' está firmado. Si su código no está preparado para eso, las cosas se romperán. –

+0

¿Puedes explicarlo un poco más? – drigoSkalWalker

+0

@Michael Burr No lo sabía, ¿tiene alguna referencia? –

0

UTF-8 No se puede suponer que los caracteres se almacenen en un byte. Los caracteres UTF-8 pueden tener entre 1 y 4 bytes de ancho. Por lo tanto, un char, wchar_t, signed o unsigned no sería suficiente para suponer que una unidad siempre puede almacenar un carácter UTF-8.

La mayoría de las plataformas (como PHP, .NET, etc.) tienen cadenas de compilación normalmente (como char[] en C) y utiliza una biblioteca para convertir codificaciones y analizar caracteres de la cadena.

+0

sí, es obvio que necesito un ARRAY de caracteres, pero mi pregunta es sobre firmados y sin firmar, piense que si tengo un ARRAY de chars chamuscado o no firmado ¿puede hacer que mi programa se ejecute incorrectamente? – drigoSkalWalker

+0

Las otras respuestas son correctas al decir que firmado/sin firmar no cambia el tamaño de los datos almacenados. Mi preocupación era que UTF-8 puede tener más de un byte para caracteres UTF-8 de kanji, árabe, etc. – spoulson

6

He tenido un par de solicitudes para explicar un comentario que hice.

El hecho de que un tipo char puede establecerse como predeterminado en un tipo firmado o sin firmar puede ser significativo cuando se comparan caracteres y se espera un cierto orden. En particular, UTF8 usa el bit alto (suponiendo que char es un tipo de 8 bits, lo cual es cierto en la gran mayoría de las plataformas) para indicar que un punto de código de carácter requiere más de un byte para ser representado.

Un ejemplo rápido y sucio del problema:

#include <stdio.h> 
int main(void) 
{ 
    signed char flag = 0xf0; 
    unsigned char uflag = 0xf0; 

    if (flag < (signed char) 'z') { 
     printf("flag is smaller than 'z'\n"); 
    } 
    else { 
     printf("flag is larger than 'z'\n"); 
    }  


    if (uflag < (unsigned char) 'z') { 
     printf("uflag is smaller than 'z'\n"); 
    } 
    else { 
     printf("uflag is larger than 'z'\n"); 
    } 
    return 0; 
} 

En la mayoría de los proyectos con los que trabajo, el tipo de adornos char Generalmente se evita a favor mediante un typedef que especifica explícitamente un unsigned char. Algo así como el uint8_t de stdint.h o

typedef unsigned char u8; 

En general se trata de un tipo de unsigned char parece funcionar bien y tienen pocos problemas - la única área que he visto problemas ocasionales es cuando el uso de algo de ese tipo para controlar un bucle:

while (uchar_var-- >= 0) { 
    // infinite loop... 
} 
3

Dos cosas:

  1. si está firmada o no un tipo char no lo hará afecta su capacidad para traducir cadenas codificadas en UTF8 hacia y desde cualquier tipo de cadena de visualización que esté usando (WCHAR o lo que sea). No se preocupe, en otras palabras: los bytes UTF8 son solo bytes, y lo que sea que esté utilizando como codificador/decodificador hará lo correcto.

  2. Algunos de su confusión puede ser que usted está tratando de hacer esto:

    unsigned char *string = "This is a UTF8 string"; 
    

    No hagas esto- que va a mezclar diferentes conceptos. Una cadena codificada en UTF-8 es solo una secuencia de bytes. Los literales de cadena C (como arriba) no fueron diseñados para representar esto; están diseñados para representar cadenas "codificadas en ASCII". Aunque en algunos casos (como el mío aquí) terminan siendo lo mismo, en su ejemplo en la pregunta, pueden no serlo. Y ciertamente en otros casos no lo serán. Cargue sus cadenas Unicode desde un recurso externo. En general, no me gustaría incorporar caracteres que no sean ASCII en un archivo fuente .c; incluso si el compilador sabe qué hacer con ellos, es posible que otro software de su cadena de herramientas no lo haga.

5

Usar unsigned char tiene sus pros y sus contras. Los mayores beneficios son que no obtiene extensión de letrero u otras características divertidas como el desbordamiento firmado que produciría resultados inesperados de los cálculos. Unsigned char también es compatible con <cctype> macros/funciones como isalpha (ch) (todas estas requieren valores en el rango de caracteres sin signo). Por otro lado, todas las funciones de E/S requieren char *, lo que requiere que realice el reparto cada vez que realice E/S.

En cuanto a UTF-8, almacenarlo en matrices con o sin signo está bien, pero debe tener cuidado con esos literales de cadenas ya que hay pocas garantías de que sean válidos UTF-8. C++ 0x agrega literales de cadena UTF-8 para evitar posibles problemas y yo esperaría que el próximo estándar C los adoptara también.

En general, debería estar bien, sin embargo, siempre y cuando se asegure de que sus archivos de código fuente siempre estén codificados en UTF-8.

0

En cuanto a you'r pregunta:

pensar si tengo una matriz chamuscado o sin firma de caracteres que se puede hacer mi programa ejecutado mal? - drigoSkalWalker

Sí. El mío lo hizo. Aquí hay un extracto ejecutable simple de mi aplicación que sale totalmente mal si se usan caracteres comunes y firmados. Intente ejecutarlo después de cambiar todos los caracteres a parámetros sin firmar. De esta manera:

int is_valid (unsigned Char c);

debería funcionar correctamente.

#include <stdio.h> 

int is_valid(char c); 

int main() { 

    char ch = 0xFE; 
    int ans = is_valid(ch); 
    printf("%d", ans); 

} 

int is_valid(char c) { 
    if((c == 0xFF) || (c == 0xFE)) { 
    printf("NOT valid\n"); 
     return 0; 
    } 
    else { 
     printf("valid\n") 
     return 1; 
    } 
} 

lo que hace es validar si el char es un byte válido dentro de UTF-8. 0xFF y 0xFE NO son bytes válidos en utf-8. ¿imagina el problema si la función lo valida como un byte válido?

lo que sucede es lo siguiente:

0xFE 
= 
11111110 
= 
254 

Si guarda esto en un char ordinaria (que se firmó) el bit más a la izquierda, bit más significativo, hace que sea negativo. Pero, ¿qué número negativo es?

Lo hace volteando los bits y agregando un bit.

11111110 
00000001 
00000001 + 00000001 = 
00000010 = 2 

y recuerde que lo hizo negativo, lo que se convierte -2

modo (-2 == 0xFE) en la función por supuesto no es verdad. lo mismo vale para (-2 == 0xFF).

De modo que una función que busca bytes inválidos termina validando bytes no válidos como si estuvieran bien: -o. otros

Dos razones me ocurre que se adhieren a firmar cuando se trata de UTF-8 es:

  1. Si es posible que tenga alguna bitshifting a la derecha, no puede haber problemas porque entonces podría terminar agregando 1 de la izquierda si usa caracteres firmados.

  2. utf-8 y unicode solo usa números positivos así que ... ¿por qué no lo haces también? manteniéndolo simple :)

Cuestiones relacionadas