(C++)UTF-16 char배열을 문자열로 바꾸는 팁
결론 먼저 : const wchar_t* ad = (const wchar_t*)buff;
C++로 C#이나 Java랑 TCP통신을 하다보면 C#이나 Java에서 Byte배열로 보낸걸 C++에서는 Char로 받아야하는 경우가 종종 있습니다.
(적어도 저의경우 하드웨어적인 제어는 C++, 소프트웨어적인 연산은 C#을 애용하기 때문에 많이 겪는경우죠.)
대표적인 예가
#include
에 있는
recv(ns, buff, 1024, 0);
이런거죠. (buff는 char배열)
여태껏은 문자열로 한글이나 영어만 보내왔기에 euc-kr로 보내면 모든게 해결되서 별로 신경쓰지는 않았지만,
요즘 하는 프로젝트가 일본어나 중국어도 지원해야 하길레 어쩔수 없이 UTF계열로 통신해야하는 문제가 발생했습니다.......
근데 생각보다 이런걸 처리하는 팁이 않보이더군요.
그래서 코드 한줄에 이걸 처리하는 방법을 적어봅니다.
const wchar_t* ad = (const wchar_t*)buff; <-코드 한줄
어때요? 깔끔하죠? ad라는 wchar_t에 문자열이 깔끔하게 담기는걸 발견하실수 있게됩니다!
문제가 있다면 UTF-8이 아닌 UTF-16만 되지만요....
(C#의 string은 UTF-16을쓰니깐 어떤의미 더 좋을수도 있습니다. C#에서 Encoding.Unicode.GetBytes(string) 을 그대로 보내주면 받아낼수 있거든요)
원리는 간단합니다.
wchar_t는 UTF-16을 사용한다.
buff가 가르키는 메모리는 UTF-16에 맞게 byte가 정렬되있다.
wchar_t가 buff가 가르키는 메모리를 wchar_t에 맞게 읽어들이면?
PROFIT!
이방법이 (MultiByteToWideChar보다) 빠르고 안정적인데 별로 알려지지 않은것 같아서 적어봅니다. :)
(wchar_t를 다른 문자열로 바꾸는 방법은 구글에 찾아보면 많이 있습니다.)
문제는 이거 역변환은 잘 안되네요......
C++ 표준에서는 wchar_t의 인코딩에 대해
C++ 표준에서는 wchar_t의 인코딩에 대해 명시하지 않고 있습니다.
구현에 따라 다르므로 wchar_t에는 UTF-16이 아니라 UTF-32로 인코딩되어 저장이 될 수도 있습니다. (int, long과 같은 타입과 마찬가지로 wchar_t의 크기 또한 표준에서는 명시하지 않습니다.)
사용하시는 시스템에서 wchar_t의 인코딩이 UTF-16이고, 해당 시스템에서만 사용할 프로그램이라면 언급하신대로 사용하셔도 큰 문제는 없습니다만 다른 환경으로의 이식성은 포기하셔야 합니다.
깨달음
그렇군요.
지금 우분투(arm용 gcc제일 최신판)랑 윈도우에서만 실험해봤는데 다른데서는 또 어떻게 될지 모르니 사용하는데 주의가 필요하겠네요.
지적해주셔서 감사합니다 :)
.
그건 어디까지나 표준 레벨에서의 이야기이고,
de facto standard 적으로는 wchar_t == UTF-16 이 맞습니다.
주류 컴파일러에서 모두 그렇게 처리하는데 그럼 사실상의 표준(de facto standard)이나 다름없는 것입니다.
참고, https://kldp.org/node/286
참고,
https://kldp.org/node/28659
----------
* 개인적으로, 가급적이면 utf-8로 모델링하는게 좋다고 생각합니다. 모든 구현은 플랫폼/프로그래밍언어 무관하게 자체에서는 맘대로, 주고/받을때는 이를(utf-8) 준수하게 하고요.
댓글 달기