시스템 프로그래밍

3. WIN32 & WIN64

CalebHong 2022. 5. 11. 11:15

64비트와 32비트의 구분 방법

* 구분의 2가지 기준

 - 한 번에 송수신이 가능한 데이터 크기(I/O 버스에 의존적)

 - 데이터 처리 능력

 

ex) 메모리에서 명령어를 I/O 버스로 Fetch할 때 한번에 처리할 수 있는 데이터 크기가 32비트인지 64인지를 구분한다. 명령어 스택에서 컨트롤 유닛으로 Decode할 때도 동일하다.

 

cf) 32비트 시스템은 32비트(4바이트) 포인터를 사용하고, 64비트 시스템은 64비트(8바이트) 포인터를 사용.

    포인터가 클수록 메모리에 접근할 수 있는 범위가 크다는 것을 의미.

    만약 32비트 시스템에서 64비트 어드레싱을 할 경우 32비트 x 2회를 해야 하기 때문에 성능이 저하됨.

    따라서 버스에서 한번에 처리할 수 있는 크기만큼 어드레싱 크기를 제한해야 함.

프로그래머 입장에서의 64비트 컴퓨터

* 32비트 → 64비트

 - 프로그램으로 표현할 수 있는 범위의 증가

   (활용 가능한 최대 메모리가 증가 - 32비트: 2의 32승, 64비트: 2의 64승)

 - 표현할 수 있는 메모리의 전체 크기

 

* 활용 가능 메모리의 확장

ex) 만약 50Byte의 메모리만을 사용할 수 있다는 극단적인 상황이라면

int _tmain(void)
{
	TCHAR str[100]; // 100Byte
    _tscanf(_T("%s"), str); // 문자열을 한 번에 읽음(필요 메모리는 100Byte)
    _tprintf(_T("%s"), str);
    return 0;
}

int _tmain(void)
{
	TCHAR ch;
    do
    {
    	_tscanf(_T("%s"), &ch); // 한 문자씩 읽음(필요 메모리는 1Byte)
        _tprintf(_T("%s"), ch);
    } while(ch != '\n'); // 널 문자를 만날 때까지
    return 0;
}

 

 

* 64비트 기반 프로그래밍

 - 64비트 시스템을 고려한 프로그래밍으로 자료형에 대해서 고려함.

 

* LLP64 vs LP64

 - 32비트 시스템과의 호환성을 중시한 모델

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

 

* 데이터 손실의 문제

 - 포인터가 당연히 4바이트라고 착각하는 오류

#include <stdio.h>

int main(void)
{
	int arr[10] = {0,};
    int arrVal = (int)arr; // 데이터 손실이 발생할 수 있는 위치(8바이트를 4바이트로 형변환하고 있음)
	printf("pointer: %d \n", arrVal);
    return 0;
}

 - 기본 자료형으로 포인터를 캐스팅해선 안 됨.

 

Windows 스타일 자료형

* Polymorphic 자료형

#if defined(_WIN64) // 64비트 기반인 경우
	typedef __int64 LONG_PTR;
    typedef unsigned __int64 ULONG_PTR;
    typedef __int64 INT_PTR;
    typedef unsigned __int64 UINT_PTR;
#else // 32비트 기반인 경우
	typedef long LONG_PTR;
    typedef unsigned long LONG_PTR;
    typedef int INT_PTR;
    typedef unsigned int UINT_PTR;
#endif

cf) PTR은 포인터 연산에 활용하기 위한 자료형임을 명시하는 것이지 자체가 포인터는 아님

 

GetLastError 함수와 에러코드

* 함수 호출의 성공여부 확인의 기본

 - GetLastError 함수 호출

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) // hFile의 문제가 있는지 확인 여부
    {
    	_tprintf("error code: %d\n", GetLastError()); // 실행 결과: error code: 2
        return 0;
    }
	return 0;
}

 - 에러 발생 확인된 이후에 바로 GetLastError 함수를 호출해야 함.