[C++ 정리] 포인터 기본 개념 및 예시 2015-06-11

포인터는 다른 변수의 위치를 가르키는 변수이다. 다음 그림과 같이 값을 담은 변수에 대하여 주소값을 가질 수 있으며 이는 프로그래밍에서 유용하게 활용 될 수 있다.

pointer
#include "stdafx.h"
#include <iostream>

using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
	int value = 1206;
	// ※ 포인터 변수는 항상 0 또는 NULL로 초기화 하고 사용할때는 항상 0 또는 NULL인지를 확인한다.
	//    - 0으로 초기화 하지 않는다면 쓰레기 값을 가지게 되고 
	//      만약 쓰레기 값이 다른 중요한 정보를 접근할 경우 
	//      심각한 문제가 발생할 여지가 있다.
	int* pointer = NULL;

	// Ex1> pointer는 포인터형 변수 이므로 value의 주소값만 받을 수 있다.
	// value 앞에 &(Ampersand)를 붙여주면 주소값이 된다.
	pointer = &value;
	// [Error]
	//pointer = value;

	// Ex2> pointer가 가리키고 있는 값을 출력할때는 앞에 *를 붙여야 한다.
	cout << "Ex2.\n";
	cout << "ADDRESS : " << pointer << "\n";
	cout << "VALUE : " << *pointer << "\n";
	cout << "\n";

	// Ex3> 포인터변수에 주소를 지정할때는 동일한 자료형의 주소만 받을 수 있다.
	float* pointer_float;
	float temp = (float)value;
	pointer_float = &temp;
	cout << "Ex3-1.\n";
	cout << "VALUE : " << *pointer_float << "\n";
	cout << "\n";
	// [Error] : 다른 자료형의 포인트 변수라면 형변환을 해주면 에러가 나지는 않지만 쓰레기 값이 출력된다.
	// - 이는 정수타입의 메모리를 실수타입으로 분석해버려서 이다.
	float* pointer_temp;
	pointer_temp = (float*)&value;
	cout << "Ex3-2.\n";
	cout << "VALUE : " << *pointer_temp << "\n";
	cout << "\n";
	// [Error] : 메모리에는 변수의 값만 저장하기 때문에 자료형을 알 수가 없기때문에 규칙위반이다.
	//pointer_temp = &value;	

	// Ex4> 포인터변수에 동일한 자료형이 아닌 주소를 받아 유연하게 사용하려면 void*를 사용한다.
	void* pointer_void;
	pointer_void = &value;
	// 사용할 때는 다시 형변환을 해주어야 한다.
	int* pointer_test = (int*)pointer_void;
	cout << "Ex4.\n";
	cout << "ORG_ADDRESS : " << pointer_void << "\n";
	cout << "NEW_ADDRESS : " << pointer_test << "\n";
	// [Error] : 원래 자료형과 다른 포인터 형이므로 규칙위반이다.
	// cout << "VALUE : " << *pointer_void << "\n";
	cout << "VALUE : " << *pointer_test << "\n";
	cout << "\n";

	// Ex5> 포인터변수 크기는 시스템의 기본연산단위를 사용한다. 자료형별 차이는 없다.
	// (16bit=>2byte, 32=>4byte, 64=>4byte)
	cout << "Ex5.\n";
	cout << "char* \t\t: " << sizeof(char*) << " bytes\n";
	cout << "int* \t\t: " << sizeof(int*) << " bytes\n";
	cout << "float* \t\t: " << sizeof(float*) << " bytes\n";
	cout << "double* \t: " << sizeof(double*) << " bytes\n";
	cout << "\n";

	return 0;
}

[C++ 정리] 명시적 형변환 & 묵시적 형변환 2015-06-11

형변환시 고려사항
큰 자료형에서 작은 자료형으로 형변환을 할 경우 일부가 잘려나갈 수 있다.

#include "stdafx.h"
#include <iostream>

using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
	float number1 = 55.55;
	int number2 = (int)number1;
	bool number3 = (bool)number1;
	cout << number2 << "\n";
	return 0;
}
포스트 링크 <[C++ 정리] 자료형의 크기 및 범위>에 따라 55.55는 각각 55(int), 1(bool)이 출력된다.

 

명시적 형변환

float number1 = 55.55;
int number2 = (int)number1;
bool number3 = (bool)number1;
변환할 자료형을 명시((int))해준다.

 

묵시적 형변환

float number1 = 55.55;
int number2 = number1;
bool number3 = number1;
그냥 대입한다.

 

명시적 형변환과 묵시적 형변환의 차이점

* 결과적인 차이는 없다
* 명시적 형변환의 경우 내부적으로 임시변수를 생성에 대입하는 방식으로 성능 저하를 일으킬 수 있다.
* 묵시적 형변환의 경우 데이터 손실에 대한 경고가 발생한다.

 

[C++ 정리] 자료형의 크기 및 범위 2015-06-11

32비트를 기준으로 한 자료형의 크기 및 범위이다. 다른 OS(16비트, 64비트)나 컴파일러에서 자료형의 크기가 조금씩 다르다는점 기억해 두자.

구분 자료형 크기 범위
기본형 void
문자형 (signed) char 1 byte -128 ~ 127
unsigned char 1 byte 0 ~ 255
wchar_t 2 byte 0 ~ 65,535
정수형 bool 1 byte 0 ~ 1
(signed) short (int) 2 byte -32,768 ~ 32,767
unsigned short (int) 4 byte 0 ~ 65,535
(signed) int 4 byte -2,147,483,648 ~ 2,147,483,647
unsigned int 4 byte 0 ~ 4,294,967,295
(signed) long (int) 4 byte -2,147,483,648 ~ 2,147,483,647
unsigned long (int) 4 byte 0 ~ 4,294,967,295
__int8 1 byte -128 ~ 127
__int16 2 byte -32,768 ~ 32,767
__int32 4 byte -2,147,483,648 ~ 2,147,483,647
__int64 8 byte -9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807
실수형 float 4 byte 3.4E-38(-3.4*10^38) ~ 3.4E+38(3.4*10^38) (7digits)
(long) double 8 byte 1.79E-308(-1.79*10^308) ~ 1.79E+308(1.79*10^308) (15digits)

 

OS별(16bit/32bit/64bit) 크기 사용의 요점은 다음과 같다.
  * int는 시스템의 기본연산 단위를 사용한다. (16bit=>2byte, 32=>4byte, 64=>4byte)
  * 64bit에서 long형을 8byte로 확장하였다. (16bit=>4byte, 32=>4byte, 64=>8byte)

 

다음코드로 자료형의 크기를 확인할 수 있다.
#include "stdafx.h"
#include <iostream>

using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
	cout << "char \t\t: " << sizeof(char) << " bytes\n";
	cout << "unsigned char \t: " << sizeof(unsigned char) << " bytes\n";
	cout << "wchar_t \t: " << sizeof(wchar_t) << " bytes\n";
	cout << "bool \t\t: " << sizeof(bool) << " bytes\n";
	cout << "short \t\t: " << sizeof(short) << " bytes\n";
	cout << "unsigned short \t: " << sizeof(unsigned short) << " bytes\n";
	cout << "int \t\t: " << sizeof(int) << " bytes\n";
	cout << "unsigned int \t: " << sizeof(unsigned int) << " bytes\n";
	cout << "long  \t\t: " << sizeof(long) << " bytes\n";
	cout << "unsigned long \t: " << sizeof(unsigned long) << " bytes\n";
	cout << "__int8 \t\t: " << sizeof(__int8) << " bytes\n";
	cout << "__int16 \t: " << sizeof(__int16) << " bytes\n";
	cout << "__int32 \t: " << sizeof(__int32) << " bytes\n";
	cout << "__int64 \t: " << sizeof(__int64) << " bytes\n";
	cout << "float \t\t: " << sizeof(float) << " bytes\n";
	cout << "double \t\t: " << sizeof(double) << " bytes\n";
	return 0;
}

data_type