[JAVA] Combien de bits fait wchar_t? Mémo de gestion des caractères larges

C'est soudain

Combien de bits wchar_t est-il défini dans wchar.h en langage C?

Pensiez-vous que c'était 16 bits? (J'ai aussi pensé) En fait, cela dépend de l'environnement. Parfois, ce n'est pas 16 bits.

** * Par souci de simplicité, nous ne considérerons pas ici les paires de substitution. ** **

Vérification

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

Quand je compile ceci avec gcc, le résultat est

est devenu. L "", qui représente des caractères larges, et wcslen (), qui compte le nombre de caractères, sont faits pour correspondre, mais la réalité de wchar_t est de 16 bits pour le premier et le dernier pour le second. Est différent de 32 bits.

Qu'est-ce qui ne va pas

Supposons que les données de chaîne Unicode données de l'extérieur soient représentées comme une chaîne terminée par un nul de 16 bits par caractère (UTF-16). Si vous essayez de sortir la chaîne de caractères et le nombre de caractères, cela ressemble au programme suivant, par exemple.

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

int main() {
  char data[] = {0x40, 0x00, 0x41, 0x00, 0x42, 0x00, 0x00, 0x00}; //Supposons que cela soit donné
  wchar_t *s = (wchar_t *)data;
  printf("%ls %d\n", s, wcslen(s));
  return 0;
}

Cependant, c'est dans un environnement où `` wchar_t '' est de 16 bits.

@AB 3

S'affiche comme prévu, mais se comporte de manière inattendue dans un environnement 32 bits.

Que faire

En C ++ 11, un type appelé char16_t '' a été créé en tant que type de données représentant un caractère de UTF-16 (à l'exclusion des paires de substitution). De même, un caractère 32 bits serait char32_t ''. La notation des littéraux de chaîne en UTF-16 / UTF-32 est également ajoutée.

Le premier exemple semble être écrit comme suit (bien qu'il s'agisse de C ++).

main.cpp


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

using namespace std;

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

Spécifiez C ++ 11 dans les options de compilation.

terminal


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

4 2 '' est émis quelle que soit la taille de wchar_t``.

Contrairement à wchar_t, char16_t n'a pas de sortie dans la fonction `` printf () ''. Au lieu de cela, cela ressemble à ceci. (Enregistrez le code source sous 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;
}

Cependant, les conditions suivantes s'appliquent à l'utilisation de `` codecvt_utf8 ''. → codecvt_utf8 --cpprefjp - Référence japonaise C ++

wchar_t trap: pour Java (JNI)

Le type char '' qui représente un caractère en Java est de 16 bits. Par exemple, dans JNI (Java Native Interface), lorsque vous souhaitez renvoyer les données de chaîne de caractères représentées par UTF-16 (terminaison nulle) en tant que type Java String ( jstring), le nombre de caractères Je suis accro au comptage avec wcslen ''.

C++Code


// jbyteArray (byte[])Étant donné l'argument de type arg
jbyte *arg_ptr = env->GetByteArrayElements(arg, NULL);
//wcslen peut donner des résultats inattendus
jstring ret_string = env->NewString((jchar *)arg_ptr, wcslen((wchar_t *)arg_ptr));
env->ReleaseByteArrayElements(arg, arg_ptr, 0);

Est-ce comme ça comme contre-mesure? (Notez la déclaration d'en-tête requise et ʻusing namespace std; `)

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

Si vous voulez juste connaître la longueur de la chaîne terminée par un nul, vous pouvez le faire vous-même en bouclant ...

wchar_t trap: pour Python (ctypes)

Il existe une bibliothèque appelée `` ctypes '' pour appeler les bibliothèques partagées C / C ++ (.dll, .so) depuis Python. Encore une fois, vous pouvez être accro à la création et à la manipulation d'un tableau de caractères Unicode à partir d'une chaîne d'octets ou à le passer à une autre fonction.

Python


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

Si wchar_t '' est un environnement 16 bits, 12 '' est émis, et s'il s'agit d'un environnement 32 bits, `` 24 '' est émis. L '«environnement» ici est comme l'environnement du compilateur utilisé pour construire Python.

En fait, create_unicode_buffer () '' lui-même peut ne pas être très utile. Lorsqu'il s'agit d'API Windows, il serait bien de traiter des arguments de type wchar_t * ''.

Résumé

wchar_t J'ai peur. wcslen J'ai peur. Je prie pour que plus de gens comme moi ne soient pas léchés et terrifiés.

Recommended Posts

Combien de bits fait wchar_t? Mémo de gestion des caractères larges
Découvrez combien de chaque caractère est dans la chaîne.