윈도우즈 시스템 프로그래밍 2장
시작 전 소개
window에서의 유니코드
아스키 코드와 유니코드를 잘 모른다면?
문자셋의 종류와 특성
🟢아스키코드: 미국에서 정의하는 표준
알파벳+수학 기호 등으로 구성되어있으며 1바이트만으로도 표현이 가능하다.
하나의 바이트만 사용하기 때문에 SBCS에 속한다.
🟢유니코드: 아스키 코드 만으로는 한글을 나타낼 수 없다.
아스키코드는 256개 뿐인데 한국의 컴퓨터에서도 수학기호 알파벳 등은 동일하게 필요하기 때문이다.
이러한 문제 때문에 나온 것이 유니코드로 각 문자당 2바이트의 용량을 사용한다.
유니코드는 WBCS에 속한다.
MBCS의 문제
때에 따라서 문자를 1바이트 또는 2바이트로 처리하기 때문에, 효율적이나 구현하는 입장에서는 주의를 요한다.
🟪한글과 영문이 섞여있는 문자열의 경우 배열의 크기가 예상과 달라질 수 있다.
char str[] = "ABC한글";
이 배열을 size로 찍어보면 ABC(3바이트)+한글(4바이트)+NULL문자(1바이트)
로 총 8이라는 숫자가 출력된다.
🟪문자열의 길이 역시 예상과 다른 값이 출력될 수 있다.
위의 코드에서 len을 찍어보면 7이 나오는데 ABC(3)+한글(4)
로 인식하기 때문이다.
char str[]="한글입니다";
를 출력하기 위해서는 문자열에 할당된 크기가 10이기 때문에
fpuc를 10번 호출하여야한다.
WBCS기반 프로그래밍
선언과 함수가 달라지게 된다.
char은 wchar_t로
wchar_t 변수는 char과 달리 2바이트의 메모리 공간이 할당된다.
L”문자열 내용”
L에 이어 등장하는 문자열은 유니코드 기반으로 표현한다는 뜻이다.
유니코드는 문자열의 끝을 의미하는 널 역시 2바이트로 처리한다.
sizeof는 연산자
함수가 아니기 때문에 배열에 어떤 것이 들어있든 우리가 원하는 배열의 크기를 반환할 수 있다.
왜 size_t의 정의에는 typedef가 들어있을까
우선 unsigned를 사용하는 이유는 크기에는 음수가 필요없기 때문이다.
typedef는 특정 시스템에서는 unsigned double로 또 다른 시스템에서는 unsigned int으로 size_t를 정의할 수 있도록 도와준다.
즉 size_t를 typedef로 추상화하고 이 덕에 특정 시스템에 종속되지 않는 특징을 가지게 된다.
그래서 호환성을 강조하는 호환성 역시 좋아진다.
또한 확장 역시 용이해진다.
프로그램의 시작점 역시 wmain로 변경
앞에서 배운 방식으로 유니코드 기반의 코딩을 하더라도 main을 wmain으로 바꾸어야 유니코드 기반으로 실행이 된다.
MBCS와 WBCS의 동시지원
windows.h 헤더
windows 시스템에 필요한 대부분의 것을 직간접적으로 나타낸다.
가변인자 함수에 대한 표준C 헤더파일, GDI함수 및 구조 정의,IME함수 정의 등의 헤더가 포험되어있다.
매크로의 경우 windef.h와 winnt.h에 정의되어있다.
LPSTR,LPWSTR?
저자분께서는 너무 감사하게도 진도의 부담을 느끼지 말란 뜻에서 정학한 이해와 암기를 권장사항처럼 서술해주셨다.
LPSTR
LPSTR에 대한 MSDN
문자의 형식은 해당 프로토콜에서 정의해야한다.
lpstr유형과 별칭인 pstr은 8비트 문자열에 대한 포인터 의미
typedef char* PSTR, *LPSTR;
위 정의를 해석하면 typedef를 통해 시스템에 상관없는 변수를 정의한다.
그리고 char*을 통해 문자열을 담는데, LPSTR로 문자열의 주소를 읽어낸다.
LPSTR과 PSTR은 똑같을까?
우선 이 설명은 gpt와 검색을 바탕으로 한 것이기 때문에 오류가 있을 수 있다.
이 둘은 기능은 동일하나 의미론 적인 차이를 가지게 될 수 있다.
pstr의 경우 일반적인 C프로그래밍 컨텍스트에서 주 사용하며, 주로 Null로 끝나는 문자열을 나타낸다.
그러나, LPSTR의 경우 주로 windowsAPI에서 활용하며 32비트와 64비트 환경에서 일반적인 포인터로 사용된다.
LPCSTR
typedef const char* LPCSTR;
로 정의되어있다. 여기서 눈여겨볼 지점은 const가 붙어있다는 것인데, 상수화를 통해 char이 가리키는 주소값을 저장하므로 내부에서의 내용변경은 불가능하다.
즉 읽기전용 상수문자열인데 이러한 방식을 통해 프로그램의 안정성을 높일 수 있다.
LPWSTR
MSDN링크
16비트 유니코드 문자열의 포인터를 나타내는 32비트 포인터
일반적으로 null로 종료된 유니코드라고 불린다.
typedef wchar_t* LPWSTR, *PWSTR;
다른 부분은 위에서 살펴보았던 내용과 동일하며, wchar_t*의 포인터인 이유는 위의 설명대로 유니코드 문자열의 포인터를 나타내기 위해서이다.
LPCWSTR
typedef const wchar_t* LPCWSTR;
로 정의되어있다. 위에서 설명한 바와 동일하게 const가 붙어있어서 가리키는 내부 문자열의 내용을 변경할 수 없다고 이해하면 된다.
MBCS와 WBCS를 동시 지원하기 위한 매크로
tcahr.h는 windows.h와 별도로 추가해야한다.
일단 유니코드 매크로에 속하면 tchar과 같은 식으로 코드가 작성되어있을텐데 이를 tchar를 wchar_t로 변환한다는 뜻으로 이해하면 된다.
또한 유니코드가 정의되어있지 않은
TCHAR arr[3]이 들어온다면
CHAR carr[3]-> char arr[3]으로 변환된다고 이해하면 된다.
즉 매크로가 알아서 유니코드로 정의된 곳에는 L”문자열내용”으로 변환하여 준다고 이해하면 된다.
만약 컴파일러상에서 매크로가 중복정의가 되어버린 경우 속성에서 지우거나
#undef를 사용하여 기존 매크로를 무효화시키는 방법도 있다.
MBCS와 WBCS 동시 지원을 위한 함수
printf->wprintf
로 string은 앞과 동일하게 L
붙이기의 방식이 있다.
앞서 말한 매크로에 대한 이해도가 높은 상태라면
_T를 사용하여
유니코드로 정의되어있으면 wprintf를 _tprintf로
그게 아니면 printf를 _tprinf로 변경하도록 만든다.
댓글남기기