Windows 에서 MBCS 와 WBCS 를 동시 지원해보자
문자셋은 크게 세 가지 형태이다
SBCS (Single Byte Character Set)
- 문자를 표현할 때 1바이트만을 사용하는 방식
- 아스키코드 (ASCII) 가 해당
MBCS (Multi Byte Character Set)
- 영문은 1바이트, 한글은 2바이트를 사용하는 방식
WBCS (Wide Byte Character Set)
- 문자를 표현할 때 2바이트만을 사용하는 방식
- 유니코드 (UNICODE) 가 해당
MBCS 기반 (코드 링크)
// MBCS 기반
#include <stdio.h>
#include <string.h>
int main(int argc, char* argv[])
{
char str[] = "ABC가나다";
printf("배열 크기 %d \n", sizeof(str));
printf("문자열 길이 %d \n", strlen(str));
for (int i = 0; i < 6; i++)
fputc(str[i], stdout);
printf("\n");
for (int i = 0; i < 10; i++)
fputc(str[i], stdout);
printf("\n");
return 0;
}
// 실행 결과
// 배열 크기 10
// 문자열 길이 9
// ABC가
// ABC가나다
실행 결과
- 배열 크기 : ABC (3바이트) + 가나다 (6바이트) + NULL (1바이트) = 10
- 문자열 길이 : ABC (길이3) + 가나다 (길이6) = 9
- ABC가
- ABC가나다
- 할당된 크기가 10바이트이므로 1바이트를 출력하는 fputc 함수를 10번 호출해야 정상 출력
WBCS 기반 (코드 링크)
// WBCS 기반
#include <stdio.h>
#include <string.h>
#include <locale.h>
int wmain(int argc, wchar_t* argv[])
{
_wsetlocale(LC_ALL, L"korean");
wchar_t str[] = L"ABC가나다";
wprintf(L"배열 크기 %d \n", sizeof(str));
wprintf(L"문자열 길이 %d \n", wcslen(str));
for (int i = 0; i < 6; i++)
fputwc(str[i], stdout);
wprintf(L"\n");
return 0;
}
// 실행 결과
// 배열 크기 14
// 문자열 길이 6
// ABC가나다
실행 결과
- 배열 크기 : ABC (6바이트) + 가나다 (6바이트) + NULL (2바이트) = 14
- 문자열 길이 : ABC (길이3) + 가나다 (길이3) = 6
- ABC가나다
wmain
- wmain 함수는 프로그램 실행 시 전달되는 문자열을 WBCS 기반으로 구성
- c:\> program.exe A1 B2 C3 의 경우 L" program.exe ", L"A1", L"B2", L"C3"
- (main 함수는 MBCS 기반으로 구성)
wchar_t 자료형
- typedef unsigned short wchar_t; 로 선언되어 있는 자료형
- 2바이트 메모리 공간을 할당하므로 유니코드 기반 문자 표현 가능
L"" 문자열
- 문자열을 유니코드 (WBCS) 기반으로 표현
- wchar_t str[] = L"ABC가나다"; 등과 같이 선언
- NULL 문자까지 2바이트로 처리
WBCS 기반 문자열 조작 함수
// size_t 는 unsigned integer 또는 unsigned __int64 (대상 플랫폼에 따라 상이)
size_t wcslen (const wchar_t* string);
wchar_t* wcscpy (wchar_t* dest, const wchar_t* src);
wchar_t* wcsncpy (wchar_t* dest, const wchar_t* src, size_t cnt);
wchar_t* wcscat (wchar_t* dest, const wchar_t* src);
wchar_t* wcsncat (wchar_t* dest, const wchar_t* src, size_t cnt);
int wcscmp (const wchar_t* s1, const wchar_t* s2);
int wcsncmp (const wchar_t* s1, const wchar_t* s2, size_t cnt);
WBCS 기반 문자열 입출력 함수
#include <locale.h> // 한글 출력 이전 헤더 포함
_wsetlocale(LC_ALL, L"korean"); // 한글 출력 이전 호출
int wprintf (const wchar_t* format [, argument]...);
int wscanf (const wchar_t* format [, argument]...);
wchar_t* fgetws (wchar_t* string, int n, FILE* stream);
int fputws (const wchar_t* string, FILE* stream);
//Windows 2000 이상의 운영체제는 모든 문자열을 유니코드 기반으로 처리
//SBCS 기반 함수 호출 시 유니코드 형식으로 변환하는 작업 필요, 프로그램 성능에 영향
Windows 에서 MBCS 와 WBCS 동시 지원 (코드 링크)
// MBCS 와 WBCS 동시 지원
// [프로젝트] -> [속성] -> [C/C++] -> [전처리기]
// [전처리기 정의] 에 기본적으로 정의
//#define UNICODE
//#define _UNICODE
// MBCS 기반 실행 시 주석 해제 (정의 해제)
//#undef UNICODE
//#undef _UNICODE
#include <stdio.h>
#include <tchar.h>
#include <windows.h>
#include <locale.h>
int _tmain(int argc, TCHAR* argv[])
{
_wsetlocale(LC_ALL, L"korean");
TCHAR str[] = _T("ABC가나다");
TCHAR input[50];
LPTSTR pStr = str;
_tprintf(_T("배열 크기 %d \n"), sizeof(str));
_tprintf(_T("문자열 길이 %d \n"), _tcslen(str));
_tprintf(_T("문자열 입력 > "));
_tscanf_s(_T("%s"), input, 40);
_tprintf(_T("%s\n"), input);
_tcscat_s(input, 50, pStr);
_tprintf(_T("%s\n"), input);
return 0;
}
// MBCS 기반 실행 결과 (9 ~ 10 주석 해제)
// 배열 크기 10
// 문자열 길이 9
// 문자열 입력 > [입력문자열]
// [입력문자열]
// [입력문자열]ABC가나다
// WBCS 기반 실행 결과
// 배열 크기 14
// 문자열 길이 6
// 문자열 입력 > [입력문자열]
// [입력문자열]
// [입력문자열]ABC가나다
실행 결과
- typedef 키워드와 매크로를 통해 MBCS 또는 WBCS 와 동일하게 동작
- _tscanf 함수는 _tscanf_s 함수 사용 및 문자열 다음 인자로 (unsigned)_countof(문자열) 추가 권장
- _tcscat 함수는 _tcscat_s 함수 사용 및 두 번째 인자로 numberOfElements 추가 권장
#include <windows.h>
- 윈도우 기반 프로그래밍에서 기본이 되는 헤더 파일
Windows 정의 자료형
- typedef 키워드를 통해 여러 자료형을 윈도우 스타일로 정의
문자
typedef char CHAR;
typedef wchar_t WCHAR;
문자열의 주소
#define CONST const // windef.h 헤더에 정의 (대문자로 const 키워드 사용)
typedef CHAR* LPSTR;
typedef CONST CHAR* LPCSTR;
typedef WCHAR* LPWSTR;
typedef CONST WCHAR* LPCWSTR;
// 위 자료형들은 winnt.h 헤더에 정의
MBCS 와 WBCS 동시 지원 매크로
// MBCS 와 WBCS 동시 지원 매크로
#ifdef UNICODE
typedef WCHAR TCHAR;
typedef LPWSTR LPTSTR;
typedef LPCWSTR LPCTSTR;
#else
typedef CHAR TCHAR;
typedef LPSTR LPTSTR;
typedef LPCSTR LPCTSTR;
#endif
#ifdef _UNICODE
#define __T(X) L ## x
#else
#define __T(x) x
#endif
#define _T(x) __T(x)
#define _TEXT(x) __T(x)
MBCS 와 WBCS 동시 지원 함수
// tchar.h 헤더에 선언
#ifdef _UNICODE
#define _tmain wmain
#define _tcslen wcslen
#define _tcscat wcscat
#define _tcscpy wcscpy
#define _tcsncpy wcsncpy
#define _tcscmp wcscmp
#define _tcsncmp wcsncmp
#define _tprintf wprintf
#define _tscanf wscanf
#define _fgetts fgetws
#define _fputts fputws
#else
#define _tmain main
#define _tcslen strlen
#define _tcscat strcat
#define _tcscpy strcpy
#define _tcsncpy strncpy
#define _tcscmp strcmp
#define _tcsncmp strncmp
#define _tprintf printf
#define _tscanf scanf
#define _fgetts fgets
#define _fputts fputs
#endif
wint_t 자료형
typedef unsigned short wint_t;
// wchar_t 및 wide end-of-file 저장 가능
참고 자료
https://learn.microsoft.com/ko-kr/cpp/c-runtime-library/standard-types?view=msvc-170
https://learn.microsoft.com/ko-kr/cpp/c-runtime-library/routine-mappings?view=msvc-170
https://learn.microsoft.com/ko-kr/cpp/c-runtime-library/data-type-mappings?view=msvc-170
https://learn.microsoft.com/ko-kr/cpp/cpp/char-wchar-t-char16-t-char32-t?view=msvc-170
https://www.youtube.com/playlist?list=PLVsNizTWUw7E2KrfnsyEjTqo-6uKiQoxc
'Windows' 카테고리의 다른 글
커널 오브젝트와 핸들 (0) | 2024.04.26 |
---|---|
표준 검색경로 (0) | 2024.04.11 |
프로세스 생성 (0) | 2024.04.10 |
오류 확인 (0) | 2024.04.09 |
64비트 기반 프로그래밍 (0) | 2024.04.03 |