64비트 기반 프로그래밍
64비트 기반 프로그래밍
64비트 시스템을 고려한 프로그래밍으로 자료형에 대해서 고려해야 한다.
LLP64 vs LP64
32비트 시스템과의 호환성을 중시한 모델
운영체제 |
모델 |
char |
short |
int |
long |
포인터 |
Windows |
LLP64 |
1b yte |
2 byte |
4 byte | 4 byte |
8 byte |
UNIX |
LP64 |
1 byte |
2 byte |
4 byte |
8 byte |
8 byte |
Windows 에서는 LLP64 모델을, UNIX 계열에서는 LP64 모델을 채택하고있는데
32비트 시스템과의 호환성을 고려하여 기존과의 차이는 포인터에서만 볼 수있다.
64비트와 32비트 공존의 문제점
데이터 손실의 문제
#include<stdio.h>
int main(void)
{
int arr[10]={0,};
int arrVal=(int)arr;
printf("pointer : %d \n ",arrVal);
return 0;
}
위 예제를 보면 arr이라는 배열의 주소값을 int형으로 강제형변환을 통하여 출력하려한다. 32비트 시스템이라면 포인터가 4byte이기때문에 문제가 발생하지 않을 것이다.
하지만 64비트 시스템이라면 arr 이 8byte 이고 int형은 4byte 이기때문에 문제가 발생 할수 있다.
※64비트 시스템에서는 포인터를 기본자료형으로 변환하지말자!
Windows 스타일 자료형
Polymorphic 자료형
#if define(_WN64)
typedef __int64 LONG_PTR;
typedef unsigned __int64 ULONG_PTR;
typedef __int64 INT_PTR;
typedef unsigned __int64 UNIT_PTR;
#else
typedef long LONG_PTR;
typedef unsigned long ULONG_PTR;
typedef int INT_PTR;
typedef unsigned int UINT_PTR;
#endif
Polymorphic 자료형은 _WIN64 를 정의 했을때 다형적 자료형이 정의된다.
하나만 예로 들어 UNIT_PTR 은 64비트일때 unsigned __int64로 해석되고
32비트일때는 그냥 unsigned int로 해석된다.
PTR이 들어가서 포인터형으로 오해 할 수 있지 Polymorphic 자료형은 포인터 타입이 아니다.
PTR이 들어간 이유는 포인터 연산을 활용하기 위한 자료형일 뿐이다.
밑의 예제를 보자.
예제3-1]
UINT CalDistance(UINT a, UINT b)
{
return a-b;
}
int _tmain(void)
{
INT val1=10;
INT val2=20;
_tprintf(_T("Position %d, %d \n"),
(UINT)&val1, (UINT)&val2);
_tprintf(_T("distance : %d \n"),
CalDistance((UINT)&val1,(UINT)&val2)
);
return 0;
}
예제를 보면 val1과 val2의 거리를 구하는 예제이다.
하지만 UINT 자료형은 4byte이다. 32비트시스템이면 몰라도 64비트시스템에서는 정상적으로 안될 수 있다.
이럴때 UINT 대신 UINT_PTR을 쓰면 32비트 일 때는 unsigned int 로
64비트 일 때는 unsigned __int64로
해석되어 문제가 발생하지 않고 메로리 낭비도 줄일 수 있다.
#if define(_WIN64)
typedef unsigned __int64 UNIT_PTR;
#else
typedef unsigned int UINT_PTR;
#endif
GetLastError 함수와 에러코드
함수호줄의 성공여부 확인의 기본
GetLastError 함수 호출
windows시스템에서 오류가 발생 할 경우 전역 메모리공간에 오류의 이유가 저장이 된다. 그래서 여기서 가져와서 해석하면되는데 이 공간의 접근을 도와주는 함수가 GetLastError 함수이다.
Constant / value |
Description |
ERROR_ARITHMETIC_OVERFLOW |
Arithmetic result exceeded 32 bits. |
ERROR_PIPE_CONNECTED 535 |
There is a process on other end of the pipe. |
ERROR_PIPE_LISTENING |
Waiting for a process to open the other end of the pipe. |
ERROR_EA_ACCESS_DENIED 994 |
Access to the extended attribute was denied. |
ERROR_OPERATION_ABORTED 995 |
The I/O operation has been aborted because of either a thread exit or an application request. |
ERROR_IO_INCOMPLETE |
Overlapped I/O event is not in a signaled state. |
ERROR_IO_PENDING 997 |
Overlapped I/O operation is in progress. |
ERROR_NOACCESS 998 |
Invalid access to memory location. |
ERROR_SWAPERROR 999 |
Error performing inpage operation. |
함수에서 반환되는 숫자로 오류를 알 수 있다.
MSDN에 가보면 더 많은 오류설명을 볼 수 있다.
실제 프로젝트에서 많이 쓰인다.
예제3-3]
int _tmain(void)
{
HANDLE hFile=
CreateFile( //Windows system 함수.
_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; 실행결과
} Error code: 2
CreateFile함수는 윈도우시스템함수이므로 크게 신경쓰지말자.
ABC.DAT 파일을 열려고 하는데 이런파일이 없다.
그래서 오류가 발생했다는것을 알고 GetLastError 함수를 호출하면 에러 코드를 얻을 수 있다.
GetLastError 함수는 에러의 발생 이유를 확인하는 함수이지 에러가 발생했는지를 확인하는 함수는 아니다.
에러가 발생하면 그 원인이 전역공간에 저장된다고 하였는데 다른 함수가 호출되면 그 값이 변할 수 있다. 그렇기 때문에
에러가 발생이 됐는지 확인 이후 어느 함수보다 GetLastError 함수가 먼저 호출해야 정확한 에러이유를 정확히 알 수있다.
'강좌 정리 > 뇌를자극하는윈도우즈시스템프로그래밍' 카테고리의 다른 글
04.장 컴퓨터 구조에 대한 두번째 이야기 ②LOAD & STORE 명령어 디자인 (0) | 2012.07.02 |
---|---|
04.장 컴퓨터 구조에 대한 두번째 이야기 ① 컴퓨터 구조의 접근방법 (0) | 2012.06.29 |
03장. 64비트 기반 프로그래밍 ① WIN32 vs WIN64 (0) | 2012.06.28 |
02장. 아스키코드 vs 유니코드 MBCS와 WBCS의 동시 지원 (0) | 2012.06.27 |
2장. 아스키코드 vs 유니코드 ①Windows에서의 유니코드(UNICODE) (0) | 2012.06.25 |