2010-03-26 17 views
10

Ho letto che C non definisce se un char è firmato o non firmato, e nella pagina GCC questo dice che può essere firmato su x86 e senza firma in PowerPPC e ARM.Char C domanda sulla codifica firmata/non firmata

Okey, sto scrivendo un programma con GLIB che definisce char come gchar (non più di questo, solo un modo per la standardizzazione).

La mia domanda è, che dire di UTF-8? Usa più di un blocco di memoria?

Dire che ho un

unsigned variabile stringa char * = "La mia stringa con il circuito di codifica UTF-8 ~> CA";

Sede, se dichiaro la mia variabile come

unsigned

avrò solo 127 valori (quindi il mio programma per immagazzinare più blocchi di MEM) o UTF-8 cambia anche in negativo?

Scusa se non riesco a spiegarlo correttamente, ma penso che sia un po 'complesso.

NOTA: Grazie per tutti rispondono

Non capisco come viene interpretato normalmente.

Penso che come ASCII, se ho un char firmato e non firmato sul mio programma, le stringhe hanno valori diferenziali, e questo porta a confondere, immaginarlo in utf8 così.

+0

Se si utilizza una macchina moderna, il char senza segno supporta i valori 0..255. Ma UTF-8 è una codifica multi-byte: utilizza 1,4 byte per ogni carattere Unicode. –

+0

Sto parlando di @Michael Burr ha detto. – drigoSkalWalker

risposta

1

Non proprio, unsigned/signed non specifica quanti valori può contenere una variabile. Specifica come sono interpretati.

Quindi, uno unsigned char ha la stessa quantità di valori di signed char, tranne che l'uno ha numeri negativi e l'altro no. È ancora 8 bit (se supponiamo che uno char contenga 8 bit, non sono sicuro che lo faccia ovunque).

+1

Lo standard C garantisce che un personaggio abbia almeno 8 bit; ci sono poche macchine a 9 bit o 10 bit lasciate. –

2

firmato/non firmato influisce solo sulle operazioni aritmetiche. se il char non è firmato, i valori più alti saranno positivi. in caso di firma saranno negativi. Ma la gamma è la stessa ancora.

1

Non fa alcuna differenza quando si utilizza un carattere * come stringa. L'unica volta firmata/non firmata farebbe la differenza se la interpretassi come un numero, come per l'aritmetica o se dovessi stamparlo come un numero intero.

+2

Può anche fare la differenza se si confrontano i personaggi. Ad esempio, nel caso UTF8, i caratteri 'flag' saranno generalmente negativi se 'char' è firmato. Se il tuo codice non è pronto per questo, le cose si romperanno. –

+0

Puoi spiegarlo un po 'di più? – drigoSkalWalker

+0

@ Michael Burr non lo sapevo, hai un riferimento? –

0

UTF-8 caratteri non possono essere presupposti per memorizzare in un byte. I caratteri UTF-8 possono essere larghi 1-4 byte. Quindi, un char, wchar_t, signed o unsigned non sarebbero sufficienti per supporre che un'unità possa sempre memorizzare un carattere UTF-8.

La maggior parte delle piattaforme (come PHP, .NET, ecc.) Si costruiscono normalmente stringhe (come char[] in C) e si utilizza una libreria per convertire tra codifiche e caratteri di analisi fuori dalla stringa.

+0

sì, è ovvio che ho bisogno di un ARRAY di caratteri, ma la mia domanda è su firmati e non firmati, penso che se ho un ARRAY di caratteri incarnato o non firmato può essere che il mio programma funziona male? – drigoSkalWalker

+0

Le altre risposte sono corrette nel dire che firmato/non firmato non modifica la dimensione dei dati memorizzati. La mia preoccupazione era che UTF-8 può essere più di un byte per caratteri UTF-8 da Kanji, arabo, ecc. – spoulson

6

Ho avuto un paio di richieste per spiegare un commento che ho fatto.

Il fatto che un tipo char possa essere impostato su un tipo con segno o senza segno può essere significativo quando si confrontano i caratteri e si prevede un determinato ordine. In particolare, UTF8 utilizza il bit elevato (supponendo che char sia un tipo a 8 bit, che è vero nella maggior parte delle piattaforme) per indicare che un punto di codice carattere richiede più di un byte da rappresentare.

Un esempio veloce e sporco 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; 
} 

Sulla maggior parte dei progetti che io lavoro, il tipo di char disadorna è in genere evitato a favore di noi utilizzando un typedef che specifica esplicitamente un unsigned char. Qualcosa come il uint8_t da stdint.h o

typedef unsigned char u8; 

In generale si tratta di un tipo di unsigned char sembra funzionare bene e hanno pochi problemi - l'unica area che ho visto problemi occasionali è quando si utilizza qualcosa di questo tipo per controllare un ciclo:

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

Due cose:

  1. se un tipo char è firmato o non firmato non lo farà influisce sulla capacità di tradurre stringhe codificate UTF8 in e da qualsiasi tipo di stringa di visualizzazione che si sta utilizzando (WCHAR o whatnot). Non preoccuparti, in altre parole: i byte UTF8 sono solo byte, e qualsiasi cosa tu stia usando come codificatore/decodificatore farà la cosa giusta.

  2. Alcuni di vostra confusione può essere che si sta cercando di fare questo:

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

    Non fare questo-- si sta mescolando concetti diversi. Una stringa codificata UTF-8 è solo una sequenza di byte. I valori letterali di stringa C (come sopra) non erano realmente progettati per rappresentare questo; sono progettati per rappresentare stringhe "codificate in ASCII". Anche se per alcuni casi (come il mio qui) finiscono per essere la stessa cosa, nel tuo esempio nella domanda, potrebbero non farlo. E certamente negli altri casi non lo saranno. Carica le stringhe Unicode da una risorsa esterna. In generale, sarei diffidente nell'includere caratteri non ASCII in un file sorgente .c; anche se il compilatore sa cosa fare con loro, altri software nella tua toolchain potrebbero non farlo.

5

L'utilizzo di char senza segno ha i suoi pro e contro. I maggiori vantaggi sono che non si ottiene l'estensione del segno o altre funzionalità divertenti come overflow con segno che generano risultati imprevisti dai calcoli. Il char unsigned è anche compatibile con <cctype> macro/funzioni come isalpha (ch) (tutti questi richiedono valori nell'intervallo di char non firmato). D'altra parte, tutte le funzioni di I/O richiedono char *, che richiede di eseguire il cast ogni volta che si esegue l'I/O.

Per quanto riguarda UTF-8, la memorizzazione in matrici con segno o senza segno è buona, ma è necessario fare attenzione con quei letterali stringa in quanto vi è poca garanzia che siano UTF-8 validi. C++ 0x aggiunge letterali stringa UTF-8 per evitare possibili problemi e mi aspetto che il prossimo standard C adotti anche quelli.

In generale si dovrebbe andare bene, tuttavia, a patto che si accerti che i file del codice sorgente siano sempre codificati in UTF-8.

0

Per quanto riguarda you'r domanda:

pensare se ho un allineamento bruciacchiato o senza segno di caratteri può essere che fare la mia corsa programma sbagliato? - drigoSkalWalker

Sì. Il mio ha fatto. Ecco un semplice ed eseguibile estratto dalla mia app che risulta completamente fuori luogo se si usano i normali caratteri firmati. Prova a eseguirlo dopo aver modificato tutti i caratteri in parametri non firmati. In questo modo:

int is_valid (unsigned char c);

dovrebbe quindi funzionare correttamente.

#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; 
    } 
} 

Quello che fa è convalidare se il char è un byte valido all'interno di utf-8. 0xFF e 0xFE NON sono byte validi in utf-8. immagina il problema se la funzione lo convalida come un byte valido?

Quello che succede è questo:

0xFE 
= 
11111110 
= 
254 

Se si salva questo in un char ordinaria (che è firmato) il bit più a sinistra, bit più significativo, lo rende negativo. Ma quale numero negativo è?

Fa questo girando i bit e aggiungendo un bit.

11111110 
00000001 
00000001 + 00000001 = 
00000010 = 2 

e ricordare rendeva negativo, così diventa -2

così (-2 == 0xFE) nella funzione naturalmente è neanche vero. stesso discorso vale per (-2 == 0xFF).

Quindi una funzione che verifica i byte non validi termina la convalida di byte non validi come se fossero ok: -o. altri

Due motivi che posso pensare di attenersi a non firmato quando si tratta di UTF-8 è:

  1. Se potrebbe essere necessario qualche bitshifting a destra, ci possono essere problemi perché allora si potrebbe finire aggiungendo 1 da sinistra se si utilizzano caratteri firmati.

  2. utf-8 e unicode utilizza solo numeri positivi quindi ... perché non lo sei anche tu? per mantenerlo semplice :)