Forum: PC-Programmierung Visual Studio - Unicode oder Multibyte?


von Tom (Gast)


Lesenswert?

Hallo,

wenn ich in Visual Studio ein neues Projekt erstelle, ist Unicode 
voreingestellt. Prüfe ich z.B. ein Laufwerk mit folgendem Code...
1
if (GetDriveType("m:\\")!=3) {}
...erhalte ich folgenden Fehler:
error C2664: 'GetDriveTypeW': Konvertierung des Parameters 1 von 'const 
char [4]' in 'LPCWSTR' nicht möglich

Stelle ich auf Multibyte um, wird ordentlich kompiliert und das Programm 
läuft. Ich könnte jetzt bei jedem Projekt Multibyte einstellen, aber ich 
frage mich, ob das so sinnvoll ist oder ob man besser mit Unicode 
programmiert? Aber was muss man - mal auf mein Beispiel bezogen - anders 
machen, um mit Unicode fehlerfrei kompilieren zu können?

Gruß,
Tom

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Wenn Du mit Unicode arbeitest, musst Du Deine Stringkonstante als 
Unicode-Stringkonstante angeben.

Das geht am einfachsten so:
1
if (GetDriveType(_T("m:\\"))!=3) {}

von Tom (Gast)


Lesenswert?

Hallo,

danke, nach dem includen von tchar.h kompiliert Visual Studio deinen 
Code ohne Fehler.
Aber ist das nicht ziemlich umständlich, jedes mal diese Klammern und 
das Text-Makro zu setzen?
Gibt es in Visual C++ 2008 Express Edition nicht die Möglichkeit, dass 
alles was in Klammern gesetzt ist, automatisch als Unicode aufgefasst 
wird? Ich meine, wenn ich in den Projektvoreinstellungen den Zeichensatz 
schon auf Unicode stelle, warum muss ich dann bei Text-Zuweisungen jedes 
mal noch explizit mit _T() umwandeln?

Wenn ich das richtig verstehe, ist der Unterschied zwischen den beiden 
Zeichensätzen der, dass bei Unicode immer 4 Byte pro Zeichen verwendet 
werden, wohingegen bei Multibyte eine variable Anzahl von Bytes(im 
besten Fall nur 2 Bytes) nötig sind. Mal angenommen ich bin Faul und 
programmiere mit Zeichensatz Multibyte...hat das - abgesehen von den 
Problemen, wenn ich bestimmte Positionen im gespeicherten Text 
anspringen möchte - später irgendwelche Nachteile(z.B. das mein Programm 
in Windows 8 unter Umständen nicht mehr läuft)?

Vielen Dank schonmal....

Tom

von Tom (Gast)


Lesenswert?

Sorry, "alles was in Klammern gesetzt ist" soll natürlich "alles was in 
Anführungszeichen gesetzt ist" heißen...

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Tom schrieb:
> Gibt es in Visual C++ 2008 Express Edition nicht die Möglichkeit, dass
> alles was in Klammern gesetzt ist, automatisch als Unicode aufgefasst
> wird? Ich meine, wenn ich in den Projektvoreinstellungen den Zeichensatz
> schon auf Unicode stelle, warum muss ich dann bei Text-Zuweisungen jedes
> mal noch explizit mit _T() umwandeln?

Stringkonstanten sind Stringkonstanten, und die sind eben vom Typ char*. 
Und char ist 8 Bit groß, unabhängig davon, ob mit Unicode- oder 
"Multibyte" gearbeitet wird.

Mit _T() kannst Du ohne großen Aufwand 16-Bit-Stringkonstanten anlegen. 
Die Alternative wäre eine Konvertierung mit Hilfe der Win32-API-Funktion 
MultiByteToWideChar.

Tom schrieb:
> Wenn ich das richtig verstehe, ist der Unterschied zwischen den beiden
> Zeichensätzen der, dass bei Unicode immer 4 Byte pro Zeichen verwendet
> werden, wohingegen bei Multibyte eine variable Anzahl von Bytes(im
> besten Fall nur 2 Bytes) nötig sind.

Teile die Zahlen durch 2, dann stimmts.

Nur mal so am Rande gefragt: Warum willst Du Unicode verwenden? 
Schreibst Du Anwendungen, die nicht mit dem in CP1252 enthaltenen 
Zeichensatz auskommen?

von René K. (king)


Lesenswert?

Rufus t. Firefly schrieb:
> Mit _T() kannst Du ohne großen Aufwand 16-Bit-Stringkonstanten anlegen.

Mit _T kannst Du aber auch ohne großen Aufwand 8-Bit-Stringkonstanten 
anlegen, je nach Art der Kompilierung. Will man wirklich nur Unicode, 
reicht ein einfaches L. Dann würde ich allerdings auch GetDriveTypeW 
anstelle von GetDriveType verwenden:
1
if (GetDriveTypeW(L"m:\\")!=3) {}


> Nur mal so am Rande gefragt: Warum willst Du Unicode verwenden?
> Schreibst Du Anwendungen, die nicht mit dem in CP1252 enthaltenen
> Zeichensatz auskommen?

Mal so am Rande gefragt: Schreibst Du tatsächlich noch Anwendungen, die 
nicht Unicode verwenden? :-)
Im Ernst: Unicode vereinfacht, zumindest unter Windows, einiges. In COM 
ist z.B. ohnehin alles Unicode. Und da unter der Haut auch alles Unicode 
ist, bringt Dir das sogar noch einen Geschwindigkeitsvorteil, da das 
Konvertieren von und nach Unicode vor und nach den Funktionsaufrufen 
entfällt.

von Peter (Gast)


Lesenswert?

René König schrieb:
> al so am Rande gefragt: Schreibst Du tatsächlich noch Anwendungen, die
> nicht Unicode verwenden? :-)
> Im Ernst: Unicode vereinfacht, zumindest unter Windows, einiges. In COM
> ist z.B. ohnehin alles Unicode. Und da unter der Haut auch alles Unicode
> ist, bringt Dir das sogar noch einen Geschwindigkeitsvorteil, da das
> Konvertieren von und nach Unicode vor und nach den Funktionsaufrufen
> entfällt.

ich muss auch sagen dasa erste was ich bei einem Projekt machen ist 
unicode abzuschalten, weil ich es noch nie gebraucht habe. Vermutlich 
würde meine Programm auch nicht laufen weil ich gerne mal ein char* 
verwende.

von René K. (king)


Lesenswert?

Peter schrieb:
> ich muss auch sagen dasa erste was ich bei einem Projekt machen ist
> unicode abzuschalten, weil ich es noch nie gebraucht habe. Vermutlich

Gebraucht habe ich das schon: Unter Windows Mobile geht es nämlich gar 
nicht anders.

> würde meine Programm auch nicht laufen weil ich gerne mal ein char*
> verwende.

Und ich verwende TCHAR*, das funktioniert mit und ohne Unicode. Man 
gewöhnt sich daran.

von Rolf Magnus (Gast)


Lesenswert?

Rufus t. Firefly schrieb:
> Tom schrieb:
>> Wenn ich das richtig verstehe, ist der Unterschied zwischen den beiden
>> Zeichensätzen der, dass bei Unicode immer 4 Byte pro Zeichen verwendet
>> werden, wohingegen bei Multibyte eine variable Anzahl von Bytes(im
>> besten Fall nur 2 Bytes) nötig sind.
>
> Teile die Zahlen durch 2, dann stimmts.

Dann ist es aber kein Unicode, denn das paßt nicht in 2 Bytes.

> Nur mal so am Rande gefragt: Warum willst Du Unicode verwenden?

Ich finde es irgendwie albern, heute noch mit dem Zeichensatzchaos 
rumzuhantieren. Gerade um das nicht zu müssen, wurde Unicode geschaffen.

von Peter (Gast)


Lesenswert?

Rolf Magnus schrieb:
> Gerade um das nicht zu müssen, wurde Unicode geschaffen.

aber meine µC verstehe keine Unicode also muss ich eh zurückwandeln. 
Auch hatte ich noch keine Probleme mit irgendwelchen Zeichensätzen. Wenn 
der User ein ü eingibt und ich bei der ausgabe ihm das gleiche zeichen 
zurück liefere ist mir doch der zeichensatz egal.

Ich musste bis jetzt noch nicht für Klingonen Software erstellen.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Rolf Magnus schrieb:
> Dann ist es aber kein Unicode, denn das paßt nicht in 2 Bytes.

Doch, tut es. MS implementiert 16-Bit-Unicode.

von Rolf Magnus (Gast)


Lesenswert?

Rufus t. Firefly schrieb:
> Rolf Magnus schrieb:
>> Dann ist es aber kein Unicode, denn das paßt nicht in 2 Bytes.
>
> Doch, tut es. MS implementiert 16-Bit-Unicode.

Meinst du USC-2? Das ist nicht 16-Bit-Unicode, sondern entspricht einem 
16-Bit-Subset von Unicode. Unicode enthält fast 110.000 Zeichen.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Die Grundlagen für die Unicodeunterstützung der ernstgemeinten 
Windows-Versionen stammen aus den frühen 90er Jahren, also aus der Zeit 
vor Unicode 2.0 (das von '96 ist).

Wenn man sich die Dokumentation* der von mir erwähnten Funktion 
MultiByteToWideChar ansieht, dann wird klar, was MS unter Unicode 
versteht:

> MultiByteToWideChar Function
>
> Maps a character string to a UTF-16 (wide character)
> string. The character string is not necessarily from
> a multibyte character set.


*) http://msdn.microsoft.com/en-us/library/dd319072%28VS.85%29.aspx

von René K. (king)


Lesenswert?

Rufus t. Firefly schrieb:
>> Maps a character string to a UTF-16 (wide character)

Und damit kann ein Character auch schon mal 4 Bytes umfassen, wenn ich 
das richtig verstehe: "In the UTF-16 encoding form, code points in the 
range U+0000..U+FFFF are represented as a single 16-bit code unit; code 
points in the supplementary planes, in the range U+10000..U+10FFFF, are 
represented as pairs of 16-bit code units."

Quelle: http://www.unicode.org/versions/Unicode5.2.0/ch02.pdf
Seite 22, unter UTF16

Und ganz genau so beschreibt es auch Microsoft, wenn ich Deinem Link 
folge: "The use of 16 bits allows the direct encoding of 65,536 
characters. In fact, the universe of symbols used to transcribe human 
languages is even larger than that, and UTF-16 code points in the range 
U+D800 through U+DFFF are used to form surrogate pairs, which constitute 
32-bit encodings of supplementary characters."

Quelle: 
http://msdn.microsoft.com/en-us/library/dd374081%28v=VS.85%29.aspx

von Rolf Magnus (Gast)


Lesenswert?

Rufus t. Firefly schrieb:
> Die Grundlagen für die Unicodeunterstützung der ernstgemeinten
> Windows-Versionen stammen aus den frühen 90er Jahren, also aus der Zeit
> vor Unicode 2.0 (das von '96 ist).

Ist also ähnlich wie bei ISO-C: Microsoft lebt weit in der 
Vergangenheit.

René König schrieb:
> Rufus t. Firefly schrieb:
>>> Maps a character string to a UTF-16 (wide character)
>
> Und damit kann ein Character auch schon mal 4 Bytes umfassen, wenn ich
> das richtig verstehe: "In the UTF-16 encoding form, code points in the
> range U+0000..U+FFFF are represented as a single 16-bit code unit; code
> points in the supplementary planes, in the range U+10000..U+10FFFF, are
> represented as pairs of 16-bit code units."

Ja, UTF-16 funktioniert ähnlich wie UTF-8, nur eben auf 16-Bit-Basis. 
Wobei ich mir unter "Wide Character" immer die mit fester Größer > 8 Bit 
vorgestellt habe und unter "Multibyte Character" die, die je nach 
Zeichen unterschiedlich groß sein können.

von Jens G. (jensig)


Lesenswert?

Das was MS als UTF-16 bezeichnet, ist nix anderes als UCS-2, also ein 
2-Byte Character Set. Genau daselbe, was man bekommt, wenn man im 
Notepad irgendwas als Unicode abspeichert. Im Hexeditor sieht man dann 
immer schön zwei Bytes pro Zeichen, egal ob es ein pures ASCII-Zeichen 
ist, oder irgendwas aus Fernost.
UTF-8 dagegen besteht aus 1 bis 4 Byte pro Zeichen - ist also variable.

von Loeti (Gast)


Lesenswert?

Jens G. schrieb:
> Das was MS als UTF-16 bezeichnet, ist nix anderes als UCS-2, also ein
> 2-Byte Character Set.

Das ist leider falsch:

Die MS Implementierung der API ist UTF-16LE, als eine mögliche Kodierung 
der Unicode-Codepoints (Codepoints sind die Hex-Werte die jedes Zeichen 
in Unicode eindeutig beschreiben).

Damit sind Unicode-Zeichen mit Codepoints U0x0 - U0xFFFF mit einem 
16bit-Wert darstellbar, während die Unicode-Zeichen mit Codepoints 
>U0xFFFF als Surrogate-Pairs (d.h. mit zwei 16bit-Werten) dargestellt 
werden.

Historisch kanne Windows NT bis NT 4.0 keine Surrogate-Pairs (waren die 
Unicode-Zeichen mit Codepoints >U0xFFFF damals überhaupt schon 
erfunden?).

Mit Windows 2000 und ff. kam die Unterstützung für Surrogate-Pairs dazu.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Loeti schrieb:
> (waren die
> Unicode-Zeichen mit Codepoints >U0xFFFF damals überhaupt schon
> erfunden?).

Nein, die kamen erst 1996 mit Unicode 2.0, so wie ich das verstanden 
habe und mich noch vage erinnere.

von Jens G. (jensig)


Lesenswert?

>Historisch kanne Windows NT bis NT 4.0 keine Surrogate-Pairs (waren die
>Unicode-Zeichen mit Codepoints >U0xFFFF damals überhaupt schon
>erfunden?).

Nun - dann war wohl mein diesbezügliches Wissen etwas altbacken ...
Aber ...

>Damit sind Unicode-Zeichen mit Codepoints U0x0 - U0xFFFF mit einem
>16bit-Wert darstellbar, während die Unicode-Zeichen mit Codepoints
>>U0xFFFF als Surrogate-Pairs (d.h. mit zwei 16bit-Werten) dargestellt
>werden.

kann trotzdem nicht stimmen, denn mindestens irgendein Wert zw. U0x0 - 
U0xFFFF muß ja als Surrogate definiert sein. Es kann also nicht U0x0 - 
U0xFFFF lückenlos als Codepointbereich für normale Zeichen herhalten.

von loeti (Gast)


Lesenswert?

Jens G. schrieb:
> kann trotzdem nicht stimmen, denn mindestens irgendein Wert zw. U0x0 -
> U0xFFFF muß ja als Surrogate definiert sein. Es kann also nicht U0x0 -
> U0xFFFF lückenlos als Codepointbereich für normale Zeichen herhalten.

Da hast Du natürlich recht, von 
http://unicode.org/faq/utf_bom.html#utf16-2
kopiert:

Q: What are surrogates?

A: Surrogates are code points from two special ranges of Unicode values, 
reserved for use as the leading, and trailing values of paired code 
units in UTF-16. Leading, also called high, surrogates are from D80016 
to DBFF16, and trailing, or low, surrogates are from DC0016 to DFFF16. 
They are called surrogates, since they do not represent characters 
directly, but only as a pair.

Somit sind (obwohl es ja gaaanz theoretisch möglich wäre ;-)
diese Codepoints als Surrogate leading und trailing UTF16-Werte 
reserviert
und können für sich allein kein Zeichen darstellen.

von loeti (Gast)


Lesenswert?

loeti schrieb:
> Somit sind (obwohl es ja gaaanz theoretisch möglich wäre ;-)

Das ist natürlich Käse, da ja gerade ein Vorteil der Surrogate-Pairs
ist daß sie beim Suchen des Strings vorwärts und rückwärts eindeutig
und schnell gefunden werden.

Bei den Multibyte Zeichensätzen und bei UTF-8 muß ja um rückwärts 
zeichen-
weise zu laufen, gleichzeitig vom Anfang der Zeichenkette nach
Mehrbyte-Zeichen gesucht werden.

von Hc Z. (mizch)


Lesenswert?

> Bei den Multibyte Zeichensätzen und bei UTF-8 muß ja um rückwärts
> zeichen-
> weise zu laufen, gleichzeitig vom Anfang der Zeichenkette nach
> Mehrbyte-Zeichen gesucht werden.

Bi irgendwelchen Multibyte-Zeichensätzen auf der Welt mag das zwar der 
Fall sein, bei UTF-8 aber genügt die Rückwärtssuche allein und ohne 
Verrenkungen.

Das erste Byte einer UTF-8-Mehrbyte-Zeichenfolge beginnt eindeutig mit 
11xxxxxx, die anderen mit 10xxxxxx.  Außerdem lässt sich am so 
gekennzeichneten ersten Byte ablesen, wie viel Bytes die Folge insgesamt 
hat.  Also besteht keinerlei Notwendigkeit, vom Anfang der Zeichenkette 
nach Mehrbyte-Folgen zu suchen.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.