[PYTHON] Wie viele Bits hat wchar_t? Breites Memo zur Zeichenbehandlung

Es ist plötzlich

Wie viele Bits ist wchar_t in wchar.h in C-Sprache definiert?

Hast du gedacht, es waren 16 Bit? (Ich dachte auch) Eigentlich kommt es auf die Umgebung an. Manchmal sind es nicht 16 Bit.

** * Der Einfachheit halber werden wir hier keine Ersatzpaare betrachten. ** **.

Überprüfung

main.c


#include <stdio.h>
#include <wchar.h>

int main() {
  wchar_t *s = L"ABCD";
  printf("%d %d\n", wcslen(s), sizeof(s[0]));
  return 0;
}

Wenn ich dies mit gcc kompiliere, ist das Ergebnis

ist geworden. L "", das breite Zeichen darstellt, und wcslen (), das die Anzahl der Zeichen zählt, werden aufeinander abgestimmt, aber die Realität von wchar_t beträgt 16 Bit für das erstere und das letztere für das letztere. Unterscheidet sich von 32-Bit.

Was ist los

Nehmen wir an, dass die von außen angegebenen Unicode-Zeichenfolgendaten als nullterminierte Zeichenfolge mit 16 Bit pro Zeichen (UTF-16) ausgedrückt werden. Wenn Sie versuchen, die Zeichenfolge und die Anzahl der Zeichen auszugeben, sieht es beispielsweise wie das folgende Programm aus.

#include <stdio.h>
#include <wchar.h>

int main() {
  char data[] = {0x40, 0x00, 0x41, 0x00, 0x42, 0x00, 0x00, 0x00}; //Angenommen, dies ist gegeben
  wchar_t *s = (wchar_t *)data;
  printf("%ls %d\n", s, wcslen(s));
  return 0;
}

Dies ist jedoch in einer Umgebung der Fall, in der wchar_t 16 Bit beträgt.

@AB 3

Wird wie erwartet angezeigt, verhält sich jedoch in einer 32-Bit-Umgebung unerwartet.

Was ist zu tun

In C ++ 11 wurde ein Typ namens "char16_t" als Datentyp erstellt, der ein Zeichen von UTF-16 darstellt (ausgenommen Ersatzpaare). In ähnlicher Weise wäre ein 32-Bit-Zeichen "char32_t". Außerdem wurde die Notation für Zeichenfolgenliterale in UTF-16 / UTF-32 hinzugefügt.

Das Beispiel am Anfang scheint wie folgt geschrieben zu sein (obwohl es C ++ ist).

main.cpp


#include <stdio.h>
#include <string>

using namespace std;

int main() {
  char16_t s[] = u"ABCD"; // UTF-Literal mit 16 Zeichenfolgen
  printf("%d %d\n", char_traits<char16_t>::length(s), sizeof(s[0]));
  return 0;
}

Geben Sie C ++ 11 in den Kompilierungsoptionen an.

terminal


g++ -std=c++11 main.cpp

4 2 wird unabhängig von der Größe von wchar_t ausgegeben.

Im Gegensatz zu wchar_t hat char16_t keine Ausgabe in der Funktion printf (). Stattdessen sieht es so aus. (Speichern Sie den Quellcode als UTF-8)

#include <string>
#include <codecvt>
#include <locale>
#include <iostream>

using namespace std;

int main() {
  char16_t s[] = u"AIUEO";
  wstring_convert<codecvt_utf8<char16_t>, char16_t> cv;
  cout << cv.to_bytes(s) << endl;
  return 0;
}

Die folgenden Bedingungen gelten jedoch für die Verwendung von "codecvt_utf8". → codecvt_utf8 --cpprefjp --C ++ Japanische Referenz

wchar_t trap: Für Java (JNI)

Der Typ char, der ein Zeichen in Java darstellt, ist 16 Bit. Wenn Sie beispielsweise in JNI (Java Native Interface) die durch UTF-16 (Nullterminierung) dargestellten Zeichenfolgendaten als Java-Typ "String" ("jstring") zurückgeben möchten, die Anzahl der Zeichen Ich bin süchtig danach, mit wcslen zu zählen.

C++Code


// jbyteArray (byte[])Angesichts des Typarguments arg
jbyte *arg_ptr = env->GetByteArrayElements(arg, NULL);
//wcslen kann zu unerwarteten Ergebnissen führen
jstring ret_string = env->NewString((jchar *)arg_ptr, wcslen((wchar_t *)arg_ptr));
env->ReleaseByteArrayElements(arg, arg_ptr, 0);

Ist es so als Gegenmaßnahme? (Notieren Sie sich die erforderliche Header-Deklaration und using namespace std;)

jstring ret_string = env->NewString((jchar *)arg_ptr, char_traits<char16_t>::length((char16_t *)arg_ptr));

Wenn Sie nur die Länge der nullterminierten Zeichenfolge herausfinden möchten, können Sie dies selbst tun, indem Sie ...

wchar_t trap: für Python (ctypes)

Es gibt eine Bibliothek namens "ctypes" zum Aufrufen von gemeinsam genutzten C / C ++ - Bibliotheken (.dll, .so) aus Python. Auch hier können Sie süchtig danach sein, ein Array von Unicode-Zeichen aus einer Folge von Bytes zu erstellen und zu bearbeiten oder es an eine andere Funktion zu übergeben.

Python


import ctypes
wstr = ctypes.create_unicode_buffer(u"AIUEO")
print(ctypes.sizeof(wstr))

Wenn wchar_t eine 16-Bit-Umgebung ist, wird 12 ausgegeben, und wenn es sich um eine 32-Bit-Umgebung handelt, wird 24 ausgegeben. Die "Umgebung" hier ist wie die Umgebung des Compilers, der zum Erstellen von Python verwendet wird.

Tatsächlich ist "create_unicode_buffer ()" selbst möglicherweise nicht sehr nützlich. Beim Umgang mit Windows-APIs wäre es hilfreich, mit Argumenten vom Typ wchar_t * umzugehen.

Zusammenfassung

wchar_t Ich habe Angst. wcslen Ich habe Angst. Ich bete, dass mehr Menschen wie ich nicht geleckt und verängstigt werden.

Recommended Posts

Wie viele Bits hat wchar_t? Breites Memo zur Zeichenbehandlung
Finden Sie heraus, wie viele Zeichen sich in der Zeichenfolge befinden.