μΉ΄ν…Œκ³ λ¦¬ μ—†μŒ

[퍼옴] L λ¦¬ν„°λŸ΄κ³Ό μœ λ‹ˆμ½”λ“œ 인코딩

ipod apple 2009. 1. 12. 20:00
λ°˜μ‘ν˜•

L λ¦¬ν„°λŸ΄κ³Ό μœ λ‹ˆμ½”λ“œ 인코딩

c++μ—μ„œ 문자λ₯Ό μ €μž₯ν•˜κΈ° μœ„ν•΄ 8 λΉ„νŠΈ 크기의 char νƒ€μž… 이외에 16 λΉ„νŠΈ 크기(μœˆλ„μš°μ—μ„œλŠ” 16 λΉ„νŠΈλ₯Ό μœ λ‹‰μŠ€ κ³„μ—΄μ—μ„œλŠ” 32 λΉ„νŠΈλ₯Ό μ‚¬μš©ν•œλ‹€κ³  ν•©λ‹ˆλ‹€.)의 μ™€μ΄λ“œ 캐릭터λ₯Ό μ €μž₯ν•˜λŠ” wchar_t νƒ€μž…μ„ μ œκ³΅ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€. wchar_t νƒ€μž…μ—λŠ” 문자의 MBCS/DBCS 및 UCSUTF-16(μœˆλ„μš°μ—μ„œλŠ” little endian을 기본적으둜 μ‚¬μš©ν•©λ‹ˆλ‹€.) 인코딩을 μ €μž₯ν•  수 μžˆμŠ΅λ‹ˆλ‹€. 또, wchar_t와 ν•¨κ»˜ μ™€μ΄λ“œ 캐릭터/λ¬Έμžμ—΄ μƒμˆ˜λ₯Ό μ§€μ •ν•˜κΈ° μœ„ν•΄ β€œL”을 μ‚¬μš©ν•©λ‹ˆλ‹€.

λ¬Έμžμ—΄μ˜ 인코딩은 μ†Œν”„νŠΈμ›¨μ–΄μ˜ globalization 을 μœ„ν•΄ ν•„μš”ν•œ μ—¬λŸ¬ μ΄μŠˆμ€‘ ν•˜λ‚˜λ‘œ MSDN 및 ꡬ글 검색을 톡해 이 λ‚΄μš©μ„ λ‹€λ£¨λŠ” λ§Žμ€ μ›Ή νŽ˜μ΄μ§€λ₯Ό 검색해 λ³Ό 수 μžˆμŠ΅λ‹ˆλ‹€. κ·Έ 쀑 μœ λ‹ˆμ½”λ“œμ™€ 캐릭터 μ…‹μ˜ 이해λ₯Ό 개발자의 ν•„μˆ˜ν•­λͺ©μœΌλ‘œ μ§€μ ν•˜κ³  μžˆλŠ” Joel Spolsky의 글을 λ³΄λŠ” 것이 도움이 될 λ“―ν•©λ‹ˆλ‹€. 이 글은 μ–Όλ§ˆμ „ jrogueλ‹˜μ΄ λ²ˆμ—­ν•œ β€œμ‘°μ—˜ 온 μ†Œν”„νŠΈμ›¨μ–΄β€λ₯Ό 톡해 ν•œκΈ€λ‘œλ„ 읽어 λ³Ό 수 μžˆμŠ΅λ‹ˆλ‹€.
또 The Complete Guide to C++ Strings, Part I - Win32 Character Encodings 도 μ°Έκ³ ν•  λ§Œν•œ λ¬Έμ„œμž…λ‹ˆλ‹€. 이 λ¬Έμ„œλŠ” ν•œκΈ€λ‘œλ„ λ²ˆμ—­λ˜μ–΄ μžˆμŠ΅λ‹ˆλ‹€.([1], [2])

λ‹€μŒμ€ wchar_t와 μœ λ‹ˆμ½”λ“œλ₯Ό λ‹€λ£¨λ©΄μ„œ μƒκ°ν•˜μ§€λ„ λͺ»ν–ˆλ˜ 문제둜 ν•˜λ£¨λ₯Ό κΌ¬λ°• λ³΄λ‚΄λ²„λ¦¬κ²Œ 된 μ΄μ•ΌκΈ°μž…λ‹ˆλ‹€.

λ¬Έμ œλŠ” wcslen() λ©”μ†Œλ“œλ₯Ό 톡해 L”" 둜 μ§€μ •λœ λ¬Έμžμ—΄μ˜ 문자수λ₯Ό μ•Œμ•„μ˜€λŠ”λ°μ—μ„œ μ‹œμž‘ν–ˆμŠ΅λ‹ˆλ‹€.

setlocale(LC_ALL, ".949");
wchar_t *wstr1 = L"abc";
printf("length: %d", wcslen(wstr1));

--- κ²°κ³Ό ---
length: 3

μ›ν•˜λŠ” κ²°κ³Όμ˜€μŠ΅λ‹ˆλ‹€. 그런데 λ‹€μŒ μ½”λ“œμ˜ κ²°κ³ΌλŠ” μ΄μƒν•©λ‹ˆλ‹€.

setlocale(LC_ALL, ".949");
wchar_t *wstr2 = L"κ°€λ‚˜λ‹€";
printf("length: %d", wcslen(wstr2));

--- κ²°κ³Ό ---
length: 6

λΆ„λͺ…νžˆ νƒ€μž…μ€ wchar_t μ΄λ―€λ‘œ κ²°κ³ΌλŠ” 3이 λ‚˜μ™€μ•Ό ν•  것 같은데 char νƒ€μž…κ³Ό strlen() ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•  λ•Œμ™€ λ§ˆμ°¬κ°€μ§€λ‘œ 6이 λ‚˜μ˜΅λ‹ˆλ‹€. κ·Έλž˜μ„œ λ©”λͺ¨λ¦¬λ₯Ό λ€ν”„ν•΄λ΄€μŠ΅λ‹ˆλ‹€. L”abc” 의 경우 λ‹€μŒκ³Ό 같이 USC-16 little endian 으둜 μ •ν™•νžˆ μ €μž₯λ˜μ—ˆμŠ΅λ‹ˆλ‹€.

61 00 62 00 63 00 00 00

그런데 λ‘λ²ˆμ§Έ Lβ€κ°€λ‚˜λ‹€β€ 의 경우

B0 00 A1 00 B3 00 AA 00 B4 00 D9 00 00 00

(μœ λ‹ˆμ½”λ“œ ν•œκΈ€ μ½”λ“œν…Œμ΄λΈ”κ³Ό KS-5601 μ½”λ“œν…Œμ΄λΈ”μ„ μ°Έκ³ ν•˜μ„Έμš”)
β€œκ°€λ‚˜λ‹€β€μ˜ DBCS 인코딩을 λ‹¨μˆœνžˆ 16λΉ„νŠΈλ‘œ μ €μž₯ν•˜κ³  μžˆλŠ” κ²ƒμ΄μ˜€μŠ΅λ‹ˆλ‹€. 참고둜 β€œκ°€λ‚˜λ‹€β€μ˜ DBCS 인코딩은 λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€.

B0 A1 B3 AA B4 D9 00

ν˜Ήμ‹œ μ§€κΈˆ μ œκ°€ μ‚¬μš© 쀑인 영문 μœˆλ„μš°μ˜ λ¬Έμ œκ°€ 아닐 까 μ‹Άμ–΄, vmwareλ₯Ό 톡해 ν•œκΈ€ μœˆλ„μš° 98 SE와 ν•œκΈ€ μœˆλ„μš° 2000을 μ‚¬μš©ν•΄ ν…ŒμŠ€νŠΈν•΄ 봐도 같은 κ²°κ³Όκ°€ λ‚˜μ˜€λ”κ΅°μš”.

μ΄λ²ˆμ—λŠ” λͺ…μ‹œμ μœΌλ‘œ MBCS λ¬Έμžμ—΄μ„ μœ λ‹ˆμ½”λ“œ(USC-16 little endian)둜 λ³€ν™˜ν•΄ wchar_t에 μ €μž₯ν•΄ λ³΄μ•˜μŠ΅λ‹ˆλ‹€.

setlocale(LC_ALL, ".949");
char *str2 = "κ°€λ‚˜λ‹€";
wchar_t wstr2_uni[blocksize];
memset(wstr2_uni, 0, blocksize * sizeof(wchar_t));
mbstowcs(wstr2_uni, str2, _mbstrlen(str2));

--- wstr2_uni의 λ©”λͺ¨λ¦¬ 덀프 ---
00 AC 98 B0 E4 B2 00 00

μ΄λ ‡κ²Œν•˜λ‹ˆ μ²˜μŒμ— μ›ν–ˆλ˜ λ°” 데둜 USC-16 little endian 으둜 μ €μž₯λ˜λ”κ΅°μš”.

결둠은

  • L”"μƒμˆ˜λŠ” λ¬Έμžμ—΄μ„ μœ λ‹ˆμ½”λ“œλ‘œ μΈμ½”λ”©ν•˜μ§€ μ•ŠλŠ”λ‹€. λ‹€λ§Œ λ¬Έμžμ—΄μ„ 16λΉ„νŠΈ wchar_t둜 μ €μž₯ν•  뿐이닀. (μ΄λ ‡κ²Œ μ €μž₯λ˜μ–΄λ„ 영문 AsciiλŠ” μœ λ‹ˆμ½”λ“œ 인코딩과 같은 κ²°κ³Όλ₯Ό 얻을 수 μžˆμŠ΅λ‹ˆλ‹€.)
  • μœ λ‹ˆμ½”λ“œλ‘œ μΈμ½”λ”©λœ λ¬Έμžμ—΄μ„ μ–»κΈ° μœ„ν•΄μ„œλŠ” MBSC둜 된 λ¬Έμžμ—΄μ„ μœ λ‹ˆμ½”λ“œλ‘œ λ³€ν™˜ν•΄ μ‚¬μš©ν•΄μ•Ό λœλ‹€.

그건 κ·Έλ ‡λ‹€κ³  치고, μ•„μ‰¬μš΄ 점은 μ œκ°€ λ³Έ μœ λ‹ˆμ½”λ“œ κ΄€λ ¨ λ¬Έμ„œλ“€μ—μ„œλŠ” L”" λ¦¬ν„°λŸ΄μ˜ 이와 같은 νŠΉμ„±μ— λŒ€ν•œ λ‚΄μš©μ€ μ°Ύμ•„λ³Ό 수 μ—†μ—ˆλ‹€λŠ” κ²ƒμž…λ‹ˆλ‹€.
μ•„λ§ˆλ„ μ •μž‘ μœ λ‹ˆμ½”λ“œμ˜ μ‚¬μš©μ΄ ν•„μš”ν•œ μ–Έμ–΄κΆŒμ˜ μ‚¬λžŒλ“€μ΄ μ“΄ 것이 μ•„λ‹Œ λŒ€λΆ€λΆ„ 영문(ν˜Ήμ€ 라틴계열 문자)을 μ‚¬μš©ν•˜λŠ” μ‚¬λžŒλ“€μ΄ μž‘μ„±ν•œ κΈ€μ΄κ±°λ‚˜ 이 글을 λ²ˆμ—­ν•œ 글이기 λ•Œλ¬ΈμΌ 것이라 생각해 λ΄…λ‹ˆλ‹€.

ps) μˆ˜μ‹­λ…„κ°„μ˜ μ†Œν”„νŠΈμ›¨μ–΄μ˜ 역사가 ν˜λ €μ§€λ§Œ 아직도 globalization은 λ‹¬μ„±ν•˜κΈ° νž˜λ“  높은 μˆ˜μ€€μ˜ μš”κ΅¬μ‚¬ν•­μ΄ μ•„λ‹κΉŒ ν•©λ‹ˆλ‹€.

update
ν˜Ήμ‹œλ‚˜ ν•˜κ³  #pragmaλ₯Ό 쑰사해보닀 #pragma setlocale()λ₯Ό λ°œκ²¬ν–ˆμŠ΅λ‹ˆλ‹€. λ‹€μŒκ³Ό 같이 μ§€μ •ν•΄μ€¬λ”λ‹ˆ L”" λ¦¬ν„°λŸ΄ λ¬Έμ œκ°€ λͺ¨λ‘ ν•΄κ²°λ˜λŠ” κ΅°μš”.

#pragma setlocale(".949")

μ’€ 더 μ•Œμ•„λ³΄κ³  ν¬μŠ€νŠΈν•  κ±Έ κ·Έλž¬μŠ΅λ‹ˆλ‹€.

λ°˜μ‘ν˜•