c++7일차
[const]
구문
const int num =1;
자료형 앞, 뒤로 const 키워드가 붙으면( 보통은 자료형 앞에 붙는다) num은 변수가 아니라 상수가 된다.(컴파일러에 의해서 상수로 취급, 주소값을 통한 변경을 막을 수는 없다.)
함수의 반환형이나 매개변수가 const 변수일 때도 동일한 의미 이다.
반드시 선언 시 초기화를 해야한다.( 초기화 때만 값을 넣을 수 있다.)
[포인터, const]
int num1 = 5;
int num2 = 10;
int* ptr = &num1;
ptr = &num2; // 주소값 변경 가능
*ptr = 1234; // 포인터가 가리키는 실재값 변경가능
상수 포인터(const pointer)
int num1 = 5;
int num2 = 10;
int* const ptr = &num1;
ptr = &num2; // 포인터가 상수 이므로 변경 불가능
*ptr = 1234; // 값은 변경이 가능
const의 우측에 포인터 변수의 값이 위치. 즉 포인터 변수를 상수화 하겠다는 뜻. 이때 선언과 동시에 초기화를 해주어야 한다. 이렇게 초기에 저장된 포인터 변수의 값은 변경이 불가능하다
상수에 대한 포인터(pointer to const)
int num1 = 5;
int num2 = 10;
const int* ptr = &num1;
*ptr = &num2; // 포인터가 상수가 아니므로 변경 가능
*ptr = 1234; // 가리키는 값이 상수이므로 변경이 불가능
const가 가장 좌측에 위치하는 경우 int* ptr 을 상수화 하겠다는 뜻. 즉 *ptr( 주소값 ptr이가리키고 있는 실재 값)이 상수가 된다. => *ptr이 가리키는 값이 상수가 되어 값을 변경할 수 없게 된다.
상수에 대한 상수 포인터(const pointer to const)
int num1 = 5;
int num2 = 10;
const int* const ptr = &num1;
ptr = &num2; // 포인터가 상수이므로 변경 불가능
*ptr = 1234; // 가리키는 값이 상수이므로 변경 불가능
주소와 값 모두 변경 할 수 없게 된다.
* const 포인터 타입을 사용하는 경우
함수의 인자를 전달 할 때, 용량이 큰 데이터는 복사로 전달하는 것보다 주소를 전달하는 게 더 이득. 이때 일반적인 주소 변수로 받아가게 되면 원복이 수정 될 여지가 있기 때문에 const 포인터 타입으로 선언해서 원본 데이터를 수정할 의도가 없음을 알리는 용도.
* 함수의 return 값은 레지스터에 지정(산술 연산 레지스터, Accumulation(EAX)) 되거나 저장(포인터 레지스터, Base Pointer(EBP)) 되는데 이 return 타입이 데이터가 너무 클 때 임시 레지스터 데이터가 감당이 되지 않는다 따라서 임시 레지스터 데이터는 주소만 가지로 함수의 결과 값을 바로 정해진 변수에 넣어 주는 방식을 사용한다.
* 데이터가 너무 클 때 그 데이터를 옮기는 비용이 있으니 최대 8byte 인 주소 값(포인터)을 사용하면 역참조해서 값을 가져오거나 수정한다. ( 일반적인 자료형보다느 구조체와 같이 큰 데이터를 갖는 경우 포인터를 사용한다)
[포인터, 배열]
배열 변수(변수명)은 배열의 첫 번째 요소의 주소를 가지고 있다.( 배열 변수가 보유한 주소 == 첫번째 요소 주소)
sizeof() 를 사용했을 때 배열은 전체 크기( 배열 길이 * 요소 크기)를, 포인터에 사용하면 메모리 주소의 크기 를 반환한다.
스케일링 : 포인터 산술 표현식을 계산할 때 컴파일러에서 피연산자에 가리키고 있는 개체의 크기를 곱하는것.
* 일반적으로 array[n]은 *(array + n)과 같다.
[void 포인터]
int IValue;
float FValue;
struct SomeThing
{
int I;
int F;
};
void* ptr;
ptr = &IValue;
ptr = &FValue;
모든 데이터 자료형을 가리킬 수 있는 특별한 타입의 포인터이다.
int num = 5;
void* ptr = #
// std::cout<< *ptr<<end; // 포이드 포인터를 역참조 할 수 없다.(error C2100: 간접 참조가 잘못되었습니다.)
int* IPtr = static_cast<int*>(ptr); // 행변환
std::<<*IPtr;
void 포인터는 어떤 데이터 자료형의 객체를 가리키는 지는 알지 못하기 때문에 직접 역참조 할 수 없다. 따라서 역참조 이전에 먼저 void 포인터를 다른 포인터 유형으로 명시적 형 변환 해주어야 한다.
* void 포인터 에서는 포인터 연산을 수행할 수 없다.
* void 포인터를 null 값으로 설정할 수 있다