Geschrieben von hannover-liga am 12.01.2006, 21:58

Kaptel 1:
1.1 Warum Unicode?
1.2 Unicode und Windows

Kapitel 2:
2.1 Einstellung im Compiler/Quelltext vornehmen
2.2 Variablentypen
2.3 Systemfunktionen
2.4 C-Funktionen mit Unicode?
2.5 MFC und Unicode

Anhang:
Links
Quellen

----- 1.1 Warum Unicode? -----

Früher war es üblich, dass Betriebssysteme auf Englisch programmiert wurden, die Befehle auf Englisch waren und keine andere Sprache benutzt wurde. Für diese eine Sprache war ASCII mit seinen 256 Zeichen völlig ausreichend. Da war sogar noch so viel Platz, dass man in die ASCII-Definition grafische Elemente aufnehmen konnte, mit denen dann "formschöne" Menüs programmiert wurden. Nachdem aber auch Europa als grosser Absatzmarkt ausserhalb der USA entdeckt wurde, stand man vor dem Problem, dass die vielfältigen europäischen Sprachen allesamt viele verschiedene Sonderzeichen mit sich brachten (im Falle von Griechisch sogar ein komplett neues Alphabet). So erfand man bei MS die Codepages (ANSI), wo durch ein "Flag" bestimmt wurde, wie einzelne Bytes dargestellt wurden. Dadurch konnte man trotzdem mit dem beschränktem Platz von einem Byte (256 Zeichen) trotzdem alle möglichen Zeichen darstellen. Doch es gab ein weiteres Problem: Wie sollte man hier den Zeichensatz einer asiatischen Sprache reinkriegen (je nach Version besitzt allein das Chinesische an die 90.000 verschiedene Zeichen)? Ausserdem gab es das Problem, dass, wenn ein Franzose einem Deutschen eine Datei schickte, manchmal aufgrund der anderen Codepage nur Müll auf dem deutschen Bildschirm auftauchte. Gerade mit dem asiatischen Sprachraum ergaben sich unlösbare Probleme für die bisherige Lösung mit den Codepages. Was macht man als Programmierer, wenn Daten nicht in eine Variable passen? Man nimmt einfach den nächst grösseren Variablentypen. Das ist eigentlich auch schon die kürzeste Definition von Unicode im Vergleich zu ASCII: 2 Byte anstatt einem Byte für jeweils ein Zeichen. Vorher gab es noch einen Zwischenschritt (Multibyte Chars), das jedoch von kaum jemandem angenommen wurde, da es äusserst komplex war (im Gegensatz zu ASCII oder Unicode gab es keine feste Breite eines Zeichens, sondern sie konnte mal einen, mal zwei Byte betragen, was dann über bestimmte Steuerzeichen angezeigt wurde).

----- 1.2 Unicode und Windows -----

Obwohl man auf der Oberfläche von Windows noch viel mit ASCII bzw. ANSI arbeitet, arbeitet die Windows NT-Reihe (also auch Win2000, WinXP, Win2003) seit der Version 4.0 intern komplett mit Unicode. Es gibt nur noch eine Handvoll von Systemfunktionen, die nur in ASCII verfügbar sind, da sie speziell auf ASCII-bezogene Themen abdecken. Auch für Softwareentwickler, die auf Windows programmieren, hat MS alles bereit gestellt, was zur Programmierung mit Unicode gebraucht wird. Obwohl Windowsprogrammierer seit nunmehr 10 Jahren komplett in Unicode programmieren könnten, ist es doch die Ausnahme, dieses zu tun. Leider wird erst später, wenn ein Programm komerziell erfolgreich wird (oder beliebte Freeware wird) auch an anderssprachige Versionen gedacht. Solange die Software weiterhin im nord- bzw. westeuropäischem Raum bleibt, ist das noch kein Problem, da auch hier die Zeichen noch per ASCII abdeckbar sind. Danach wird es aber schwierig und für viele ist der Aufwand dann einfach zu gross, den ganzen Quelltext nochmal anzufassen, um ihn Unicode-konform zu machen.

----- 2.1 Einstellung im Compiler/Quelltext vornehmen -----

Eigentlich ganz einfach. Man muss nur folgende Zeile in seine erste Headerdatei schreiben:
#define _UNICODE

Je nach Compiler kann man dies auch in den Projektoptionen festlegen.
Man muss dieses nicht festlegen, wenn man manuell jeweils die Unicode- oder ASCII-Versionen von Variablentypen und Funktionen benutzt. Das ist allerdings relativ aufwendig und macht es einem schwierig, wieder in die andere Version zu wechseln.

----- 2.2 Variablentypen -----

wchar_t ist das 2-Byte-Äquivalent zu char. Es gibt noch ein paar andere Variablentypen, die allerdings kaum gebraucht werden. Schlau wie MS ist, haben sie es uns Programmierern noch einfacher gemacht. Es wurde der Typ _TCHAR in der Headerdatei tchar.h definiert, der je nachdem, ob _UNICODE definiert wurde oder nicht, entweder ein define für wchar_t oder (ohne _UNICODE) ein define für char ist. Eigentlich ist das eigentlich auch schon alles.
Ein anderes Problem ist die Darstellung von Zeichenketten. Normalerweise arbeitet man so:
char szBlubb[] = "Hallo";

Analog dazu würde das in einem Unicode-Programm so aussehen:
wchar_t szBlubb[] = "Hallo";

Dies ist leider nicht ganz richtig. Für den Compiler sind konstante Zeichenketten immer noch ganz normale "1-Byte"-Arrays. Um dem Compiler klar zu machen, dass wir eine Unicode-Zeichenkette im Sinn haben, müssen wir das Makro "L" verwenden. Das sieht dann so aus:
wchar_t szBlubb[] = L"Hallo";

Genauso funktioniert das auch mit einzelnen Zeichen:
szBlubb[1] = L'e';

Auch hier war Microsoft so nett, uns die Arbeit zu erleichtern, falls wir zwischen ASCII und Unicode hin- und herschalten. Mit "_T" bezeichnete Zeichenketten bzw. einzelne Zeichen werden, je nachdem ob _UNICODE definiert wurde oder nicht, entweder einfach ignoriert (ASCII) oder zu "L" verwandelt (Unicode).
Man sollte am besten einfach in seinem Programm statt char bzw. wchar_t den "Typen" _TCHAR verwenden und vor jede konstante Zeichenkette bzw. jedes konstante Zeichen ein _T setzen (statt gar nichts oder L). Um dann zwischen ASCII- und Unicode-Programm zu wechseln, braucht man nur noch die Definition von _UNICODE wegzulassen bzw. hinzuzufügen.

----- 2.3 Systemfunktionen -----

Auch hier macht es uns Microsoft sehr einfach. Von fast jeder Funktion aus der Windows-API gibt es zwei Versionen. Eine ist für die Unicode-Version zuständig, die andere für die ASCII-Version. Am Beispiel von der Funktion MessageBox() soll das hier mal exemplarisch erklärt werden:
Die Funktion MessageBox() gibt es eigentlich gar nicht. Das ist nur eine Defintion, die je nach definiertem oder nicht definiertem _UNICODE auf eine der beiden folgenden Funktionen gemappt wird:
MessageBoxA() ==> ASCII- bzw. ANSI Version
MessageBoxW() ==> Unicode-Version (W für "wide char")

Dies ist in der WinAPI-Dokumentation nicht explizit beschrieben, weil man sich 100%-ig darauf verlassen kann, dass dies für alle WinAPI-Funktionen zutrifft.
Also ist auch hier für uns Programmierer verdammt einfach, Unicode zu benutzen.

----- 2.4 C-Funktionen mit Unicode? -----

MS hat es uns faulen Programmierern bisher schön einfach gemacht. Doch was ist mit den ganzen Funktionen der Standard C-Bibliothek? Diese wurde ja nicht von MS festgelegt. Leider wurde diese Bibliothek lange Zeit vor den Überlegungen zu Unicode standardisiert. Daher wurde auf Bequemlichkeit für Programmierer weniger Wert gelegt, da dies nur als Randerscheinung behandelt wurde. Aus diesem Grund liegt jede Funktion auch zwar hier zwei Mal vor, allerdings ist kein define switch eingebaut worden, der die Benutzung eines einzigen Namens erlauben würde. Als Beispiel mal die bekannte Funktion printf():
ASCII-Variante: int printf( const char *format [, argument]... );
Unicode-Variante: int wprintf( const wchar_t *format [, argument]... );

Wer in Unicode programmiert und Teile aus der Standard C-Bibliothek benutzt, muss die entsprechende Unicode-Version der oftmals viel bekannteren ASCII-Funktion raussuchen.
Microsoft hat auch hier versucht, es uns einfacher zu machen und in seine Dokumentation (MSDN) immer beide Versionen auf der gleichen Seite aufgeführt.
Falls ihr also nichts findet, in der Online-MSDN unter http://msdn.microsoft.com nach der C-Funktion suchen, die ihr benutzen wollt. Dort findet ihr dann beide Versionen.
An einer anderen Stelle hat MS dann noch speziell beide Versionen einer jeden Funktion über Defines zusammengeführt, so dass man diese Version ebenso benutzen kann, wie bei der WinAPI. In der Headerdatei tchar.h sind die Defines so angelegt, dass automatisch zwischen ASCII- und Unicode-Version gewechselt werden kann. Allerdings heissen diese Defines wieder ganz anders. Hier eine Übersicht der Defines mit den zugehörigen ASCII- und Unicode-Versionen (falls der Link nicht mehr funktioniert, die Headerdatei tchar.h anschauen):
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclib/html/_crt_routine_mappings.asp
(In der Tabelle ist ASCII mit SBCS/Single Byte Character Strings bezeichnet. Mit "Generic-Text routine name" sind die Defines gemeint. Die Spalte MBCS braucht nicht beachtet zu werden.)

----- 2.5 MFC und Unicode -----

Die MFC arbeitet fast ausschliesslich mit CString, wo immer Zeichenketten auftauchen. Wer in diese Klasse reinschaut, wird entdecken, dass auch dort die oben gemachten Defines genutzt werden. Also ist die MFC ASCII- UND Unicode-kompatibel. Im Zweifelsfall sollte man aber mal in den Quelltext der MFC-Klassen reinschauen.

----- Links: -----
Seite der Unicode-"Macher": http://www.unicode.org
Portalseite Unicode MSDN: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclib/html/_crt_Generic.2d.Text_Mappings.asp

Infos über Unicode:
http://unicode.e-workers.de
http://de.wikipedia.org/wiki/Unicode
http://www.lrz-muenchen.de/services/sonstiges/unicode_data

----- Quellen -----
MSDN - http://msdn.microsoft.com
frei aus dem Kopf nach:
Charles Petzold, "Windows Programmierung", ISBN 3860634879, Microsoft Press Deutschland

hannover-liga ist ein Zweitnick von 0-checka (http://www.lima-city.de/profile.php?id=18270)

Bewertung Anzahl
6
100,0 %
1 Bewertungen