IT공부/IT서적

[뇌를 자극하는 윈도우즈 시스템 프로그래밍] 3장. 64비트 기반 프로그래밍

shine94 2024. 12. 21. 23:28

* 해당 글은 윤성우의 뇌를 자극하는 윈도우즈 시스템 프로그래밍 도서를 읽고 정리한 글입니다

   https://product.kyobobook.co.kr/detail/S000001223395

 

뇌를 자극하는 윈도우즈 시스템 프로그래밍 | 윤성우 - 교보문고

뇌를 자극하는 윈도우즈 시스템 프로그래밍 |

product.kyobobook.co.kr

 

* 번에 송수신할 수 있는 데이터 크기와 한 번에 처리할 수 있는 데이터 크기를 기준으로

   32비트 컴퓨터와 64비트 컴퓨터를 구분 짓는다

 

* 프로그래머 입장에서는 표현할 수 있는 주소값의 범위가 넓으면 좋다

   왜? 메모리 공간만 충분하다면, 주소값의 범위가 넓은 만큼 더 넓은 메모리 공간을 활용할 수 있기 때문

 

* 데이터 표현 모델

운영체제 모델 char short int long 포인터
Windows LLP64 1바이트 2바이트 4바이트 4바이트 8바이트
UNIX LP64 1바이트 2바이트 4바이트 8바이트 8바이트

 

* 64비트 시스템에서는 포인터가 가지고 있는 주소값을 4바이트 정수형으로 형 변환하지 말자!

 

* Windows 스타일 자료형

WINDOWS 자료형 의미  
BOOL Boolean variable typedef int BOOL
DWORD 32bit unsigned integer typedef unsigned long DWORD
DWORD32 32bit unsigned integer typedef unsigned int DWORD32
DWORD64 64bit unsigned integer typedef unsigned __int64 DWORD64
INT 32bit signed integer typedef int INT
INT32 32bit signed integer typedef signed int INT32
INT64 64bit signed integer typedef signed __int64 INT64
LONG 32bit signed integer typedef long LONG
LONG32 32bit signed integer typedef signed int LONG32
LONG64 64bit signed integer typedef signed  __int64 LONG64
UINT Unsigned INT typedef unsigned int UINT
UINT32 Unsigned INT32 typedef unsigned int UINT32
UINT64 Unsigned INT64 typedef unsigned __int64 UINT64
ULONG Unsigned LONG typedef unsigned int ULONG
ULONG32 Unsigned LONG32  typedef unsigned int ULONG32
ULONG64 Unsigned LONG64  typedef unsigned __int64 ULONG64
PINT INT32에 대한 포인터 typedef int* PINT
PINT32 INT32에 대한 포인터 typedef signed int* PINT32
PINT64 INT64에 대한 포인터 typedef signed __int64* PINT64
PLONG LONG에 대한 포인터 typedef LONG* PLONG
PLONG32 LONG32에 대한 포인터 typedef signed int* PLONG32
PLONG64 LONG64에 대한  포인터 typedef signed __int64* PLONG64
PUINT UINT에 대한  포인터 typedef unsigned int* PUINT
PUINT32 UINT32에 대한  포인터 typedef unsigned int* PUINT32
PUINT64 UINT64에 대한  포인터 typedef unsigned __int64* PUINT64
PULONG ULONG에 대한  포인터 typedef ULONG* PULONG
PULONG32 ULONG32에 대한  포인터 typedef unsigned int* PULONG32
PULONG64 ULONG64에 대한  포인터 typedef unsigned __int64* PULONG64

 

* Polymorphic 자료형

   PTR 때문에 포인터라고 오해하지 말자!

Polymorphic 자료형 WIN64 WIN32
LONG_PTR __int64 long
ULONG_PTR unsigned __int64 unsigned long
INT_PTR __int64 int
UINT_PTR unsigned __int64 unsigned  int

 

#include <stdio.h>
#include <tchar.h>
#include <windows.h>

// 주의! 32비트 환경에서 테스트하기!

UINT CalDistance(UINT a, UINT b)
{
	return a - b;
}

int _tmain(void)
{
	INT val1 = 10;
	INT val2 = 20;

	_tprintf(_T("Position %u, %u\n"), (UINT)&val1, (UINT)&val2);
	_tprintf(_T("distance : %u\n"), CalDistance((UINT)&val1, (UINT)&val2));

	return 0;
}

ㄴ 주의! 32비트 환경에서 테스트하기

ㄴ 디버그 빌드시 distance 12, 릴리즈 빌드시 distance 4

 

#include <stdio.h>
#include <tchar.h>
#include <windows.h>

UINT_PTR CalDistance(UINT_PTR a, UINT_PTR b)
{
	return a - b;
}

int _tmain(void)
{
	INT32 val1 = 10;
	INT32 val2 = 20;

	_tprintf(_T("distance : %d\n"), CalDistance((UINT_PTR)&val1, (UINT_PTR)&val2));

	return 0;
}

ㄴ 결과(특히, 릴리즈 부분에 대한 결과를 보고 싶다면 최적화 컴파일러를 꺼야 볼 수 있다)

   ① 릴리즈

        32비트 : 4

        64비트 : 4(0x000000cee76ffcf4 - 0x000000cee76ffcf0)

   ② 디버그

        32비트 : 12(0x001DF738 - 0x001DF744)

        64비트 : -32(0x000000383B9FF9B4 - 0x000000383B9FF9D4)

        32비트 정렬 규직 4바이트, 64비트 정렬 규칙 8바이트

        각각 정렬 규칙에 맞춰서 디버그는 할당된 변수 기준으로 위 아래 빈 공간을 둠

        따라서 위와 같은 결과값들이 나오게 됨

 

* Windows 시스템 함수를 호출하는 과정에서 오류가 발생하면, GetLastError 함수 호출을 통해 오류의 원인을 확인할 수 있다

   https://learn.microsoft.com/ko-kr/windows/win32/debug/system-error-codes

 

자습서 - 시스템 오류 코드 디버그 - Win32 apps

WinError.h 헤더 파일에 정의된 시스템 오류 코드 및 링크 디버깅에 대한 지침을 제공합니다.

learn.microsoft.com

 

#include <stdio.h>
#include <tchar.h>
#include <windows.h>

int _tmain(void)
{
	HANDLE hFile = CreateFile(_T("ABC.DAT"), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
	if (hFile == INVALID_HANDLE_VALUE)
	{
		_tprintf(_T("error code: %d\n"), GetLastError());
		return 0;
	}
	return 0;
}

 

#include <stdio.h>
#include <tchar.h>
#include <windows.h>

int _tmain(void)
{
	HANDLE hFile = CreateFile(_T("ABC.DAT"), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
	
	_tprintf(_T("error code: %d\n"), GetLastError());

	hFile = CreateFile(_T("ABC2.DAT"), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

	_tprintf(_T("error code: %d\n"), GetLastError());

	return 0;
}

 

* Window 시스템 함수가 호출될 때 마다 GetLastError 함수가 반환하는 에러코드는 갱신된다