C++

[강의] 9월 26일 수업정리

k-codestudy 2024. 9. 27. 03:54

오늘은 배열과 포인터의 관계에 대한 수업을 했다.

 

일차원 배열과 포인터

#include <iostream>

int main()
{

	int arData[3]{ 3,2,1 };
	int* p{};

	p = &arData[0];

	printf("%d\n", *p);
}

간단한 예시를 들어보자

현재 포인터 p에 arData [0]의 주소값이 들어가 있기에 출력을 하면 3이라는 값이 나오게 될 것이다.

 

#include <iostream>

int main()
{

	int arData[3]{ 3,2,1 };
	int* p{};

	p = arData;

	printf("%d\n", *p);
}

이 코드에서 p = arData;는 p = &arData [0];와 동일하게 작동한다.

배열 이름인 arData는 첫 번째 요소의 주소를 나타내므로, p는 첫 번째 요소의 주소를 가지게 된다.

따라서 *p는 동일하게 arData [0]의 값인 3을 출력한다.

요약:

  • arData는 배열의 첫 번째 요소의 주소의 의미도 가질 수 있다.
  • &arData [0]도 배열의 첫 번째 요소의 주소를 가리킨다.
  • 두 방식 모두 p를 배열의 첫 번째 요소로 가리키게 하며, *p의 결과는 arData [0]의 값인 3이 출력된다.

 

printf("%d\n", *p);
printf("%d\n", p[0]);

 

*p는 포인터 p가 가리키는 메모리 주소의 값을 의미한다.

p [0]는 배열 표기법을 사용하여 포이너가 가리키는 배열의 첫 번째 요소를 참조한다. 이 표현은 사실상 *(p + 0)과 동일하기에 p가 가리키는 주소에서 0만큼 떨어진 값을 가져오는 것이다.

 

결론:

  • *p는 포인터 p가 가리키는 주소의 값을 직접 가져오는 연산.
  • p [0]은 포인터를 배열처럼 다루며 *(p + 0)과 동일하게 작동하여 첫 번째 요소의 값을 가져온다.
  • 둘 다 결국 arData [0]의 값인 3을 출력하게 되므로 결과가 동일하다

이와 같은 이유로 *p와 p [0]는 동일한 결과를 출력하게 됩니다.

 

 

이차원 배열과 포인터

#include <iostream>

int main()
{

	int arData[2][3]{ {6,5,4},{3,2,1} };
	int (*p)[3]{};
	int *pData{};

	p = arData;
	pData = *p;

	printf("%p\n", p);
	printf("%p\n", pData);
}

int arData [2][3]{{6,5,4}, {3,2,1}};

  1. arData는 2 * 3 배열로, 두 개의 행과 세 개의 열을 가진 이차원 배열 

int (*p)[3];

  1. p는 크기가 3인 정수 배열을 가리키는 포인터이다. 즉, p는 int [3] 타입의 배열을 기리 킬 수 있다
  2. p = arData는 p가 arData의 첫 번째 행(arData [0])을 기리 키도록 설정한다.

int *pData;

  1. pData는 일반적인 정수형 포인터이다.
  2. pData = *p는 p가 가리키는 배열(arData [0])의 첫 번째 요소의 주소를 pData에 저장한다. 이는 pData = &arData [0][0]과 돌일한 의미를 가지게 된다.

출력 결과:

printf("% p\n", p);

  1. p는 arData [0]의 주소를 가리키므로, p는 arData의 첫 번째 행의 주소를 출력한다.
  2. 예를 들어, arData [0]의 주소가 0x1000이라면 p도 0x1000을 출력한다.

 

printf("% p\n", pData);

  1. pData는 p가 가리키는 배열(arData [0])의 첫 번째 요소의 주소를 가리킨다
  2. 따라서 pData도 arData [0][0]의 주소를 출력합니다. 이 역시 0x1000으로 동일하다

 

2차원 배열과 포인터 요약

int (*p)[3]는 하나의 자료형으로 생각해라

  1. int(*p)[3]은 크기가 3인 정수 배열을 가리키는 포인터의 의미를 가지게 된다.
  2. 즉, p는 int [3]이라는 정수 세 개로 이루어진 배열을 가리킬 수 있다.

2차원 배열에서 포인터의 주소 대입

  1. p = arData에서 arData는 2차원 배열로 int [3] 묶음이 여러 개 있는 것이다.
  2. arData는 첫 번째 int [3] 묶음 (arData [0])의 주소를 의미한다.

큰 묶음과 작은 묶음의 개념

  1. 2차원 배열은 큰 묶음(int [3])안에 작은 묶음(int)이 여러 번 들어간 구조로 이해할 수 있다.
  2. 큰 묶음이 몇 번 들어가냐에 따라 2차원 배열, 1차원 배열로 생각하면 쉽게 이해 가능하다.



 

아래에 출력 예시를 남겨두겠다. ( 주석으로 어떤 결과가 나오는지 정리 해둠 )

#include <iostream>

int main()
{
    int arData1[3]{ 3, 2, 1 };                   // 1차원 배열 선언
    int arData2[2][3]{ {6, 5, 4}, {3, 2, 1} };   // 2차원 배열 선언 (2행 3열)
    int(*p)[3] {};                               // 3개의 정수를 담는 배열에 대한 포인터 선언
    int* p2;                                     // 포인터 선언
    
    int* pData{};

    p = arData2;                                 // p가 arData2의 첫 번째 행을 가리킴

    printf("%p\n", arData2);                 // arData2 첫 번째 행의 주소 출력 (0x 주소 형태)
    printf("%p\n", &arData2);                // 2차원 배열 전체의 주소 출력 (arData2와 동일)
    printf("%p\n", *arData2);                // 첫 번째 행의 첫 번째 요소 주소 출력 (arData2[0][0]의 주소와 동일)

    printf("%p\n", arData2);                 // '%p'를 사용하여 주소를 출력해야 함
    printf("%p\n", arData2 + 1);             // arData2의 두 번째 행의 주소 출력
    printf("%p\n", &arData2 + 1);            // arData2의 마지막 주소 다음의 주소 출력
    printf("%p\n", *arData2 + 1);            // 첫 번째 행에서 두 번째 요소의 주소 출력 (arData2[0][1]의 주소)


    p = &arData1;                                // 1차원 배열 arData1의 주소를 p에 할당
    printf("%d\n", (*p)[2]);                     // arData1의 세 번째 요소 (1) 출력

    p = arData2;                                 // arData2 첫 번째 행의 주소를 p에 할당
    printf("%d\n", (*p)[2]);                     // arData2의 첫 번째 행 세 번째 요소 (4) 출력

    p = arData2 + 1;                             // arData2의 두 번째 행을 가리킴
    printf("%d\n", (*p)[1]);                     // arData2[1][1]의 값 (2) 출력

    p = arData2;                                 // 다시 arData2 첫 번째 행의 주소를 p에 할당
    printf("%d\n", (*(p + 1))[0]);               // arData2[1][0]의 값 (3) 출력
    printf("%d\n", p[1][0]);                     // 동일한 결과로 arData2[1][0]의 값 (3) 출력

    p = &arData1;                                // arData의 주소를 포인터 p에 할당
    pData = *p;                                 // 배열의 첫 번째 요소 주소를 pData에 할당

    printf("%d\n", *pData);                     // pData가 가리키는 값 (3) 출력
    printf("%d\n", (*p)[2]);                    // arData의 세 번째 요소 (1) 출력

    p2 = arData1;                                 // arData의 첫 번째 요소 주소를 p에 할당

    printf("%d\n", *(p2 + 1));                   // p가 가리키는 두 번째 요소 (2) 출력
    printf("%d\n", p2[1]);                       // 동일한 결과로 두 번째 요소 (2) 출력
}