C++/C++ : Study

C++ 포인터 참조자 (4) 배열과 포인터, Const

더블유제이플로어 2024. 9. 21. 01:41

포인터 배열 배열처럼 나란히 선언하기에

역참조 안 하고 배열 호출 그대로 사용할 수 있다.

그럼 배열과 포인터의 차이점을 알아보자.


Arrays and Pointers

●  배열의 이름은 배열의 첫 요소의 주소를 가리킨다. (remind)

●   포인터 변수의 값은 주소값이다.

●  포인터 변수와 배열이 같은 주소를 가리킨다면, 포인터 변수와 배열은 (거의) 동일하게 사용 가능하다.

        ☞ (차이점 : 배열은 주소값을 정의 이후 변경 불가. Sizeof() 반환값이 다름)

	int scores[] = { 100,95,90 };
	cout << scores << endl; // 0x00000047752FFAC8
	cout << *scores << endl; // 100
	cout << scores[0] << endl; // 100

	int* score_ptr = scores;
	cout << score_ptr << endl; // 0x00000047752FFAC8
	cout << *score_ptr << endl; // 100
    	cout << score_ptr[0] << endl; // 100

여기서 말하는 배열은 정적 배열을 말한다.

int main()
{
	int arr[] =  { 1,2,3 };
	cout << arr << endl;
}

이렇게 작성할 경우 콘솔 값은 

000000D7B21FF7D8 가 나온다.

arr은 arr[0] 의 주솟값을 가리킨다.


포인터는 메모리값에 주소값만 들어갈 수 있다.

포인터 변수와 배열이 같은 주소를 가리키게 된다면 포인터 변수와 배열은 동일하게 사용이 가능하다.



	int scores[] = { 100,95,90 };
	cout << sizeof(scores) << endl; // 12

	int* score_ptr = scores;
	cout << sizeof(score_ptr) << endl; // 4
    // Debug x86

출력값이 다르다

정적인 배열은 배열 안의 요소들의 전체적인 개수만큼  sizeof 값에 반환된다.

하지만 포인터는 주소값을 가지고 있기 때문에 int 포인터인 만큼 sizeof 값에 4byte  반환된다.

그렇기에 int num =10; 이라는 변수를 선언하고

배열에 변수의 주솟값은 넣을 수 없고,

포인터에는 변수의 주솟값을 넣을 수 있다.

	int num = 10;
	int scores[] = { 100,95,90 };
	cout << sizeof(scores) << endl;
	scores = &num; //Fail

	int* score_ptr = scores;
	cout << sizeof(score_ptr) << endl;
	score_ptr = &num;

●  array_name[index] == pointer_name [index]

●  *(array_name + index) == *(pointer_name + index)

	int scores[] = { 100,95,90 };
	int* scores_ptr = scores;

	cout << scores_ptr << endl; //0033FA94
	cout << (scores_ptr + 1) << endl; //0033FA98
	cout << (scores_ptr + 2) << endl; //0033FA9C

	cout << *scores_ptr << endl; //100
	cout << *(scores_ptr + 1) << endl; //95
	cout << *(scores_ptr + 2) << endl; //90

	cout << scores_ptr[0] << endl; //100
	cout << scores_ptr[1] << endl; //95
	cout << scores_ptr[2] << endl; //90

인덱스 [0] [1]에 대한 의미인지

포인터를 만들 때 타입을 명시하도록 했는지

전반적으로 파악할 수 있다.

배열의 주소에 1을 더하면 두 번째 주솟값이 보인다.

int는 4byte 이므로

끝자리만 보면 4 -> 8 -> C(12)로 4 byte씩 이동한 걸 알 수 있다.

표현을 +1 , +2으로 표현을 했지만 실질적으로는

scores_ptr + 1*sizeof(int) 만큼 이동하는 것이다.

+1이라는 건 1칸이 아니라 int 형에서의 다음칸을 의미한다.

그럼 double 형일 때는 어떨까? (double 8 byte)

	double scores[] = { 100,95,90 };
	double* scores_ptr = scores;

	cout << scores_ptr << endl; //010FFA40
	cout << (scores_ptr + 1) << endl; //010FFA48
	cout << (scores_ptr + 2) << endl; //010FFA50

	cout << *scores_ptr << endl; //100
	cout << *(scores_ptr + 1) << endl; //95
	cout << *(scores_ptr + 2) << endl; //90

	cout << scores_ptr[0] << endl; //100
	cout << scores_ptr[1] << endl; //95
	cout << scores_ptr[2] << endl; //90

8 byte씩 주소값이 증가한 것을 알 수 있다.

포인터의 타입이 알고 있어야

컴파일러가 포인터의 인덱스를 접근할 때

몇 byte씩 띄어서 볼 수 있는지 알 수 있다.


Const and Pointer

●  const의 포인터 (pointers to const)

●  const인 포인터 (const pointers)

● const의 const 인 포인터 (const pointers to const)


간략하게라도 외워둘 것

const int a = 10;

변수에 const를 사용하는 것처럼

포인터에도 const를 사용하는 방법이 3가지가 있다.


Const and Pointer

●  const의 포인터 (pointers to const)

    ▶ 데이터가 const / 포인터는 다른 데이터를 가리킬 수 있다.

	int high_score = 100;
	int low_score = 60;
	const int* score_ptr = &high_score;

	*score_ptr = 80; // ERROR
	score_ptr = &low_score; // OK

int 포인터 앞에 const가 붙여져 있다면

데이터가 const로 된다.

그 뜻은 *score_ptr의 값, 즉 high_score의 메모리 값을 const로 지정하였기에

값 변경이 되지 않는다.

대신 score_ptr이 다른 메모리 주소값을 가질 수는 있다.


Const and Pointer

●  const의 포인터 (pointers to const)

●  const인 포인터 (const pointers)

     포인터가 const / 데이터는 변할 수 있다.

	int high_score = 100;
	int low_score = 60;
	int* const score_ptr = &high_score;

	*score_ptr = 80; // OK
	score_ptr = &low_score; // ERROR


Const and Pointer

●  const의 포인터 (pointers to const)

●  const인 포인터 (const pointers)

●  const 의 const 인 포인터 (const pointers to const)

     둘 다 const 인 경우

	int high_score = 100;
	int low_score = 60;
	const int* const score_ptr = &high_score;

	*score_ptr = 80; // ERROR
	score_ptr = &low_score; // ERROR

데이터도 변경이 안되고 포인터도 변경이 안된다.

const의 위치에 따라서 동작이 다르기 때문에 외워두는 게 좋다.

https://youtu.be/1 g4 KLKS6 AP0? si=DlAP97 PAAz5 cNHeE