wide char, mbyte char, Unicode



  • Hallo Zusammen,

    habe ein Verstaendnisfrage zum Thema "Unicode":
    wenn ich ein array von Typ wchar_t deklariere und einen
    Wert darauf zuweise, muss jeder unicode char jeweils in
    4 bytes gespeichert werden?

    /* 24 byte wchar_t array */ 
    wchar_t* unistr = L"hello" ;
    

    und wenn obiges Beispiel in multibyte string durch wcstombs() umwandelt wird,
    heisst es dass die minimum Anzahl der Bytes zurueckgegeben wird,
    womit man Unicode string darstellen kann( fuer hello: 5 bytes).

    Definiert ANSI-C standardmaessig die Groesse des Typs wchar_t als
    32 bit? Oder ist es wiederum OS abhaengig?

    Danke.



  • wchar_t muss so gross sein wie ein 'int', also mindestens 16 bit.
    32 bits sind ja die reinste verschwendung.
    irgendwo (ich glaub in limits.h) sind die konstanten WCHAR_MIN und WCHAR_MAX.
    🙂



  • __fricky schrieb:

    wchar_t muss so gross sein wie ein 'int', also mindestens 16 bit.
    32 bits sind ja die reinste verschwendung.

    Hallo __fricky,

    verstehe.. es muss mindestens so gross wie ein 'int' sein... Allerdings
    verstehe ich nicht warum 32bit die reinste Verschwendung sein kann. Es wird
    unten bei der Link gesagt, dass die volle chinesische Alphabet mehr als
    65000 Chars hat.
    http://docs.sun.com/app/docs/doc/802-5776/6i9gsvj0e?l=ko&a=view
    Ich haette mich gefreut wenn wchar_t standardmaessig 32bit waere, ich will
    ja chinesisch unbedingt unterstuetzen :P.

    Wegen 16bit Allokierung: Werden dann alle c-strings nur als mbyte strings
    behandelt? Oder wird es erst bei einem Ueberlauf auf mbyte Speicherung
    umgeschaltet?

    /* ist 5 byte or 10byte,weil 16bit?*/
    wchar_t* unistr = L"hello" ;
    

    __fricky schrieb:

    irgendwo (ich glaub in limits.h) sind die konstanten WCHAR_MIN und WCHAR_MAX.
    🙂

    /usr/include/bits/wchar.h:24:#define __WCHAR_MAX (2147483647l)
    😉



  • L"hello" sollte 12 bytes haben.
    🙂



  • __fricky schrieb:

    L"hello" sollte 12 bytes haben.
    🙂

    ...wegen dem Terminierungszeichen '\0', welches ebenfalls 2Byte groß ist.



  • __fricky schrieb:

    wchar_t muss so gross sein wie ein 'int'

    Nö, woher hast du das?

    ISO C99 schrieb:

    wchar_t
    which is an integer type whose range of values can represent distinct codes for all
    members of the largest extended character set specified among the supported locales;

    __fricky schrieb:

    32 bits sind ja die reinste verschwendung.

    Nein, nach dem Standard ein Muss, wenn das System Unicode 4/5 unterstützt.

    __fricky schrieb:

    L"hello" sollte 12 bytes haben.
    🙂

    Nö, 24 bytes.

    @jsbach

    Was willst du denn genau machen? Für Unicode-Support könnte sich vielleicht eher UTF-8 lohnen. http://en.wikipedia.org/wiki/UTF-8

    http://www.cl.cam.ac.uk/~mgk25/unicode.html#c



  • rüdiger schrieb:

    __fricky schrieb:

    wchar_t muss so gross sein wie ein 'int'

    Nö, woher hast du das?

    ISO C99 schrieb:

    wchar_t
    which is an integer type whose range of values can represent distinct codes for all
    members of the largest extended character set specified among the supported locales;

    ich weiss nicht mehr woher, aber falsch in erinnerung.
    auf windosen jedenfalls (zumindest auf etwas älteren) besteht wchar_t aus 2 bytes.
    🙂



  • __fricky schrieb:

    ich weiss nicht mehr woher, aber falsch in erinnerung.
    auf windosen jedenfalls (zumindest auf etwas älteren) besteht wchar_t aus 2 bytes.
    🙂

    Das ist aber nicht konform mit dem Standard. Das rührt einfach daher, dass für die ersten Unicode-Versionen 2byte genug waren und MS will das aus Gründen der Kompatibilität nicht ändern und benutzt daher UTF-16, was das ganze aber noch mehr broken macht, da das ganze eben nicht auf Multibyte-Zeichensätze ausgelegt ist.



  • rüdiger schrieb:

    Das ist aber nicht konform mit dem Standard. Das rührt einfach daher, dass für die ersten Unicode-Versionen 2byte genug waren und MS will das aus Gründen der Kompatibilität nicht ändern und benutzt daher UTF-16, was das ganze aber noch mehr broken macht, da das ganze eben nicht auf Multibyte-Zeichensätze ausgelegt ist.

    standard hin oder her, windows stammt noch aus der vor-standardzeit und m$ vertickerte windoze damals schon in chinesisch. im windosen kernel sind z.b. alle strings utf-16. alle winapi-funktionen, die zeichenketten entgegennehmen, gibt es in 2-facher ausführung (einmal mit char* und einmal mit wchar_t*). eine änderung auf utf-32 oder utf-8 würde wohl kaum einen gewinn bringen. deshalb lassen sie's so.
    🙂



  • __troll schrieb:

    rüdiger schrieb:

    Das ist aber nicht konform mit dem Standard. Das rührt einfach daher, dass für die ersten Unicode-Versionen 2byte genug waren und MS will das aus Gründen der Kompatibilität nicht ändern und benutzt daher UTF-16, was das ganze aber noch mehr broken macht, da das ganze eben nicht auf Multibyte-Zeichensätze ausgelegt ist.

    standard hin oder her, windows stammt noch aus der vor-standardzeit und m$ vertickerte windoze damals schon in chinesisch. im windosen kernel sind z.b. alle strings utf-16. alle winapi-funktionen, die zeichenketten entgegennehmen, gibt es in 2-facher ausführung (einmal mit char* und einmal mit wchar_t*). eine änderung auf utf-32 oder utf-8 würde wohl kaum einen gewinn bringen. deshalb lassen sie's so.
    🙂

    bla bla bla



  • blablubb schrieb:

    __fricky schrieb:

    rüdiger schrieb:

    Das ist aber nicht konform mit dem Standard. Das rührt einfach daher, dass für die ersten Unicode-Versionen 2byte genug waren und MS will das aus Gründen der Kompatibilität nicht ändern und benutzt daher UTF-16, was das ganze aber noch mehr broken macht, da das ganze eben nicht auf Multibyte-Zeichensätze ausgelegt ist.

    standard hin oder her, windows stammt noch aus der vor-standardzeit und m$ vertickerte windoze damals schon in chinesisch. im windosen kernel sind z.b. alle strings utf-16. alle winapi-funktionen, die zeichenketten entgegennehmen, gibt es in 2-facher ausführung (einmal mit char* und einmal mit wchar_t*). eine änderung auf utf-32 oder utf-8 würde wohl kaum einen gewinn bringen. deshalb lassen sie's so.
    🙂

    bla bla bla

    so ist das halt auf den internet-boards.
    🙂



  • rüdiger schrieb:

    __fricky schrieb:

    wchar_t muss so gross sein wie ein 'int'

    Nein, nach dem Standard ein Muss, wenn das System Unicode 4/5 unterstützt.

    Wie stellt man das fest bei 0S? Gibt's einen Macro dafuer? Wuerde
    ein check von __STDC_ISO_10646__ ausreichen?

    rüdiger schrieb:

    @jsbach

    Was willst du denn genau machen? Für Unicode-Support könnte sich vielleicht eher UTF-8 lohnen. http://en.wikipedia.org/wiki/UTF-8

    http://www.cl.cam.ac.uk/~mgk25/unicode.html#c

    Danke fuer die Links. Das Protokoll, das ich schreibe soll UTF-8 unterstuetzen.
    Dabei moechte ich fuer jeden char einen festen Groesse von Bytes(4) haben anstatt
    multibyte encoding oder decoding. Das waere dann simpler.



  • jsbach schrieb:

    rüdiger schrieb:

    __fricky schrieb:

    wchar_t muss so gross sein wie ein 'int'

    Nein, nach dem Standard ein Muss, wenn das System Unicode 4/5 unterstützt.

    Wie stellt man das fest bei 0S? Gibt's einen Macro dafuer? Wuerde
    ein check von __STDC_ISO_10646__ ausreichen?

    mach doch sizeof(wchar_t). das müsste dann 2,3, oder 4 ausspucken. also je nachdem wie breit es bei dir ist.

    jsbach schrieb:

    Das Protokoll, das ich schreibe soll UTF-8 unterstuetzen.
    Dabei moechte ich fuer jeden char einen festen Groesse von Bytes(4) haben anstatt
    multibyte encoding oder decoding. Das waere dann simpler.

    das wär aber doof, weil der trick bei utf-8 ist ja gerade, dass unicode platzsparend gespeichert oder übertragen wird.
    🙂



  • fricky schrieb:

    jsbach schrieb:

    Das Protokoll, das ich schreibe soll UTF-8 unterstuetzen.
    Dabei moechte ich fuer jeden char einen festen Groesse von Bytes(4) haben anstatt
    multibyte encoding oder decoding. Das waere dann simpler.

    das wär aber doof, weil der trick bei utf-8 ist ja gerade, dass unicode platzsparend gespeichert oder übertragen wird.
    🙂

    Na das Problem ist, ich muss alles in einem byte order rueberschieben.
    Wenn ich den multibyte methode benutzen wuerde, heisst ja dann dass ich
    jeden char nach einem Muster vergleichen muss , damit ich feststellen kann um
    wie viel Bytes es fuer diesen wchar tatsaechlich geht. Erst dann waere ich in
    der Lage swap_bytes() in little_endian auszufuehren.
    Wenn ich aber festen Laenge habe, spare ich mir diesen Mustervergleich.

    Da ich im Bereich Unicode Anfaenger bin, stelle ich ne Frage: Sowie ich von
    Unicode verstanden habe, kann man auch feste Laenge fuer jeden
    Char benutzen. Ist es dann nicht mehr UTF-8 encoding?



  • jsbach schrieb:

    Ist es dann nicht mehr UTF-8 encoding?

    richtig. bei utf-8 haben die zeichen variable längen, während du utf-32 verwenden willst. bei utf-32 belegt jedes zeichen immer 4 bytes.
    🙂



  • meiner meinung nach sind 4 byte pro zeichen zu viel. soweit ich weiß, kann man in allen lebenden sprachen alles ausdrücken, was man will, wenn man 2 byte verwendet. außerdem gibt es kaum schriftarten, die alle buchstaben darstellen würden. sind ja bereits 1,1 millionen.

    utf8 in strings zu verwenden, bringt vermeintlich einen vorteil, wird aber dann bei indiziertem zugriff auf einen buchstaben kompliziert, da man vom start des strings weiterzählen muss, da die buchstaben ja nicht alle gleich lang sind. ein einfaches start + n * index klappt da nicht mehr.



  • besserwisser schrieb:

    meiner meinung nach sind 4 byte pro zeichen zu viel. soweit ich weiß, kann man in allen lebenden sprachen alles ausdrücken, was man will, wenn man 2 byte verwendet. außerdem gibt es kaum schriftarten, die alle buchstaben darstellen würden. sind ja bereits 1,1 millionen.

    utf8 in strings zu verwenden, bringt vermeintlich einen vorteil, wird aber dann bei indiziertem zugriff auf einen buchstaben kompliziert, da man vom start des strings weiterzählen muss, da die buchstaben ja nicht alle gleich lang sind. ein einfaches start + n * index klappt da nicht mehr.

    UTF-8 ist ja auch nicht dafür gemacht, sondern zur effizienten Speicherung.



  • fricky schrieb:

    jsbach schrieb:

    Ist es dann nicht mehr UTF-8 encoding?

    richtig. bei utf-8 haben die zeichen variable längen, während du utf-32 verwenden willst. bei utf-32 belegt jedes zeichen immer 4 bytes.
    🙂

    danke fuer die Erklaerung. Ich habe mich fuer UTF-8 entschieden und
    implementiert.

    Eine andere Sache was mich ueberrascht hat, dass die byte order von unicode
    endianness ist. Also ein multibyte char (von 3 byte Laenge) wird auf x86 in dem
    gleichen byte Reihenfolge gespeichert wie bei sparc. Ich habe mir eigentlich die
    Speicherung umgekehrt -genauso wie standarde datentypen(int, short als2bytes, long)- vorgestellt.



  • Ist doch egal wie, hauptsache einheitlich.



  • Wie macht man aus einem wide char array ein ansi char array?



  • zuhülfe schrieb:

    Wie macht man aus einem wide char array ein ansi char array?

    Meinst du mit Wide-Char wirklich Wide-Char oder doch Multi-Byte?
    Bei einem Wide-Char musst du einfach nur Wide-Char für Wide-Char durchgehen, alles was in ein char passt, größentechnisch, kannst du direkt in char Casten, alles andere kannst du nicht mit ansi darstellen und dafür ein Placeholder einfügen, z.B. ?
    Vorausgesetzt das Wide-Char Array enthält Zeichen in einem Zeichencode der den Ansi-Zeichensatz in die ersten 255 Zahlen mappt.


Anmelden zum Antworten