변수 명명법
표준 함수들은 모두 이방식대로 인수 이름을 작성하므로 접두어들을 외우고 있으면 함수의 인수가 어떤의미인가를 쉽게파악할수있다.
윈도우즈 프로그래밍에서쓰는 이런 변수 명명법을 헝가리식 명명법이라고 한다.(이렇게 쓰면 편하다는 것이지 꼭 지켜야하는 의무는 아니다)
BOOL InvalidateRect(HWND hWnd, CONST RECT *lpRect, BOOL bErase);
다음함수의 원형을 보면 hWnd는 핸들이고, lpRect는 포인터이며, bErase는 진위형이라는것을 쉽게 알수 있다.
위 표는 윈도우즈에서 사용자 정의 데이터형이다. 이 데이터형은 windows.h라는 헤더파일에 typedef로 선언되어있으며,
마치 표준 데이터형처럼 사용함으로 알아두면 유용하다.
◎핸들에 대한 이해
- 핸들이란 구체적인 어떤 대상에 붙여진 번호이며 문법적으로 32비트의 정수값이다.
윈도우에서는 여러가지 종류의 핸들이 사용되고있으며, 만들어진 윈도우에 윈도우 핸들(hWnd)을 붙여 번호로 관리한다.
DC에 대해서도 핸들을 사용하고 논리적펜, 브러시 에도 핸들을 붙여 관리한다.
※핸들의 특징
①핸들은 일단 정수값이며, 대부분의 경우 32비트 값이다. 핸들을 사용하는 목적은 오로지 구분을 위한 것이므로, 핸들끼리 중복
되지 않아야하며, 이런 목적으로는 정수형이 가장 적합하다. 정수형은 비교나 대입 연산이 가장 빠른 타입이므로,핸들로 쓰여
지기적합하다.
②핸들은 운영체제가 발급하며, 사용자는 쓰기만 한다. 윈도우를 만들거나 파일을 열면 운영체제는 만들어진 윈도우나 열려진
파일에 핸들을 붙이고, 그값을 리턴한다. 사용자는 이 핸들을 잘 보관해 두었다가 해당 윈도우나 파일을 다시 참조 할 때 사용
한다. 사용자가 직접핸들을 만드는 경우는 없다.
③같은 종류의 핸들끼리는 절대 중복된 값을 가지지않는다.(대상을 구분하는 원래의 목적을 달성할수 없기 때문), 하지만 다른
종류의 핸들끼리는 중복된 값을 가질수도 있다.
④핸들은 정수형이므로 값을 가지겠지만 그 실제값이 무엇인지는 몰라도 상관없다. 핸들은 단순 표식일 뿐이다. 핸들형 변수를
만들어 핸들을 대입받아 쓰고 난후에는 버리면 된다.
-윈도우즈에서 핸들은 예외없이 접두어 H로 시작되며 핸들값을 저장하기 위해 별도의 데이터형까지 정의해 두고 있다.
HWND,HPEN,HBRUSH,HDC등이 핸들을 담기 위한 데이터형들이며 모두 부호없는 정수형이다.
●비트 OR연산자
- 사용자가 원하는 작업을 하기 위해 함수를 호출한다. 이때 함수에게 작업의 내용을 전달하는 인수가 같이 건네지는데, 인수에는
작업의 목적과 방법을 지정하는 정보가 포함된다.
전달가능한 옵션이 여러개 있을 경우 필요한 옵션수 만큼 인수를 전달받는것이아니라, 하나의 인수에 복수개의 옵션을 묶어
전달하는데 이때 사용되는 연산자가 비트OR연산자(|)이다.
CreateWindow 함수는 만들고자 하는 윈도우의 스타일을 인수로 전달 받는데 WS_CHILD,WS_CAPTION,WS_BORDER등 옵션
이 수십개나 되지만 단 하나의 인수로 이옵션을 모두 전달 받는다.
비트 OR연산자를 사용하면 관심없는 인수는 생략해버릴수도 있고, OR연산은 교환 법칙이 성립하므로 값의 순서에 무관하게
여러가지 옵션을 묶어서 전달하므로 호출 속도도 빠르다.
여러개의 옵션을 비트 OR연산자로 묶어 하나의 정수값만 전달하더라도 함수는 인수의 개별비트를 테스트 한후 어떤 옵션
이 선택되었는지를 알수 있다. 각 옵션의 실제 값이 어떻게 정의 되어있는 가는 알 필요가 없으며, 매크로 상수만 알면되는데
매크로 상수가 곧 옵션의 이름이다.
●유니코드
TCHAR는 C의 기본 타입 중 하나인 char와 같지만 유니코드로 컴파일할때는 wchar_t타입이된다. wchar_t는 실제로 unsigned short로 정의 되어있으며 부호 없는 16비트 정수 형이다.TCHAR타입의 실제 정의문은 조건부 컴파일로 작성되어있다.
#ifdef UNICODE typedef wchar_t TCHAR; #else typedef char TCHAR; #endif |
char를 바로쓴 소스를 유니코드로 바꿀때는 일일이 소스를 뜯어 고쳐야하지만, TCHAR라는 중간 타입을 사용한 소스는 프로젝트 설정에 따라 소스도 같이 바뀌는 효과가 있으므로 소스는 그대로두고 컴파일할수 있다.
문자열을 다루는 함수들도 가급적으로 유니코드를 인식하는 함수를 사용한다.
유니코드 인식함수들은 표준 함수와 이름이 비슷하되 앞에 l가가 하나 더 붙는다는 것만 다르며, 운영체제가 제공하는 API함수이므로 별도의 용량을 차지하지않는다는 장점이있다.
strlen은 char타입의 문자열 길이만 조사하지만 lstrlen은 TCHAR 타입이 문자열에 대해서도 동작하므로 이식이 훨씬 더유리하다.
문자열 상수도 타입이있으므로 겹따옴표안에 바로 문자열상수를 쓰지말고, TEXT 매크로로 둘러 싸는 것이 좋다.
TCHAR *str="string"; //x TCHAR *str=TEXT("string"); //TEXT매크로 안에 문자열 상수를 쓴다. |
TEXT매크로는 유니코드 설정에 따라 문자열 상수의 타입을 변경한다. 유니코드로 컴파일할때는 각 문자가 16비트의 유니코드
문자가되며 그렇지 않을 때는 8비트의 안시(ANSI)문자가 된다.
유니코드로 컴파일 하면 세계의 모든 문자를 단일 코드체계로 표현할수 있어 국제화에 유리하다는 장점이있다.
●64비트 API
64비트에서 달라지는 가장 큰 차이점은 주소 공간이 확대됨으로 해서 포인터의 크기가 64비트로 확장되었다는 점이다.
포인타 타입외 int나 long형은 여전히 32비트를 유지하는데 이런 정수 타입까지 64비트로 확장하면 낭비가 너무 심하기 때문이다.64비트개발 환경은 이식의 편의를 위해 여러가지 중간타입을 제공하는데 고정타입보다는 가급적이면 중간 타입을 사용하는것이 유리하다.
실행되는 환경에 상관없이 일정한 길이를 가져야한다면 이타입을 사용한다. INT32는 항상 32비트의 부호있는 정수형이며,
INT64는 항상 부호있는 64비트 정수 이다.
INT_PTR,LONG_PTR,ULONG_PTR,DWORD_PTR, |
뒤에 _PTR이 붙은 타입은 운영체제의 비트수에 따라 크기가 가변적이며 포인터와 같은 길이를 가진다. 포인터와 호환되어야 하는 정수가 필요할때는 이타입을 사용해야한다.