기초CS - 포인터 4

킴스코딩클럽·2022년 10월 13일
1

CS기초 시리즈

목록 보기
33/71

배열과 포인터

배열은 (상수)포인터다
포인터는 배열이다 (x)

int main()
{
	int array[3]{};
	for (int i = 0; i < 3; i++)
	{
		std::cout << &array[i] << std::endl;
		//출력하면 int타입이므로 4바이트씩 떨어져서 
		//즉 바로 옆에 붙어있다
	}

	int* p = &array[0]; //첫번째 원소의 주소


	std::cout << p; //첫번째 주소 : array[0]
	std::cout << p + 1;//4바이트만큼 떨어진 다음 주소 : array[1]
	std::cout << p + 2;//array[2]

	int* p = array; //첫번째 원소의 주소는 이렇게 사용할 수 있게됨
}

배열의 주소

배열 0번 원소의 주소가 배열의 이름과 같다

int main()
{
	int array[3]{};
	for (int i = 0; i < 3; i++)
	{
		std::cout << &array[i] << std::endl
	}

	//int* p = &array[0]; 첫번째 원소의 주소
	int* p = array; 0번 원소의 주소가 배열의 이름과 같다

	std::cout << p; //첫번째 주소 : array[0]
	std::cout << p + 1;//4바이트만큼 떨어진 다음 주소 : array[1]
	std::cout << p + 2;//array[2]
}

포인터로 배열 부르기

int main()
{
	int array[3]{1,2,3};
	for (int i = 0; i < 3; i++)
	{
		std::cout << &array[i] << std::endl;

	}

	int* p = array; //첫번째 원소의 주소
	
	for (int i = 0; i < 3; i++)
	{
		std::cout << *p << std::endl;
		p++;
	}
	//위의 결과와 똑같은 결과가 나옴
	for (int i = 0; i < 3; i++)
	{
		std::cout << array+i << std::endl;
		//주소값이 출력됨
		std::cout << *(array + i) << std::endl;
        //위와 같은 결과
        array++: 
        //불가능 : 상수포인터이기 때문에
	}

2차 배열과 포인터의 상관관계

실제로 오류가 자주나옴

int array[2][3]{};
	for (int row = 0; row < 2; row++)
	{
		for (int col = 0; col < 3; col++)
		{
			std::cout << &array[row][col] << std::endl;
		}
	}
	std::cout << "___________" << std::endl;
	std::cout << array[0] << std::endl;//array0 는 첫번째 원소의 주소
	std::cout << array[1] << std::endl;//array1 은 두번째 열 첫번째 원소의 주소

	std::cout << array << std::endl; //array0의 주소가 나오게됨

	std::cout << array[0] + 1 << std::endl;
	//array0에서 옆으로 한 칸 이동
	std::cout << array[0] + 2 << std::endl;
	//array0에서 옆으로 두 칸 이동
	std::cout << array[0] + 3 << std::endl;
	//array[0][3]의 의미 : 문제없이 컴파일됨->포인터에는 배열이라는 정보가 없음
	std::cout << array[0] + 6 << std::endl;
	//배열을 넘어갔지만 컴파일됨 : 포인터는 단순히 메모리 주소만 가지고 연산함
	std::cout << *(array[0] + 6) << std::endl;
	//만든 배열을 넘어가게됨
	*(array[0] + 6) = 10;
	//포인터가 넘어가서 주소를 부르는 것은 가능하지만 변수를 저장하는 것은 불가능함
	


	std::cout << array << std::endl;
	std::cout << array + 1 << std::endl;
	//타입의 크기만큼 건너뜀
	//array[0][0]:int타입 array[0][0]가 모두 사용되었기 때문
	//array[0]:array[0]는 int세개인 배열을 가리키는 int[3]타입 array[0]가 쓰였기 때문에 빠짐
	//array : int[2][3]타입
	//[2]는 행이고  행 안으로들어가면 [3]개의 열이 들어간다

포인터에는 타입이 존재함
p+1을 하면 타입만큼 1칸 건너뛰는 것임

2차원 배열의 포인터 문법

int main()
{
	int array[2];
	int* p = array; //int[2] >>int*

	int array2[2][3]{};
	int** pp = array2;
	//타입을 몇개 건너야 하는지 정보가 없음
	//int[2][3] >>int[2]int*>>int**
	
	int* p2[3] = array2;
	//int*rk 3개인 배열

	int(*p)[3] = array2
	//연산자 우선순위와 관련됨
	//int 3개인 배열을 가리키는
}

C언어의 문법 구조

int ((*p1)(int))[10] = nullptr;
어떻게 읽을까???

우리가 compiler가 되어보자

컴파일러의 작동방식

  • 오른쪽에서 왼쪽

아래 두 표현은 같은 뜻
const int a; // a는 정수인데 상수인
int const a; // a는 상수인데 정수인


포인터의 경우
const int *p; 
// p point to int constant
// p는 상수정수를 가리키는 포인터
// 가리키는 대상이 상수 정수인 포인터
*p = 1; 상수이므로 값을 바꿀 수 없음 불가능
p = &x; 가리키는 대상은 가능


int * const p; 
// constant p point to int
// p는 상수 포인터인데 정수를 가리키는
// 상수 포인터
*p = 1; 값은 바꿀 수 없음
p = &x; 가리키는 대상은 바꿀 수 없음


int const * p; 
//p는 상수정수를 가리키는 포인터와 같은 의미
//컴파일러 개념을 알면 이걸로 쓰기도 함
//외국은 이 방식 선호하기도 함 읽는 방시때문
// *p
  • 식별자를 찾는다(identifier: 변수명,함수명...)
  • 식별자의 오른쪽으로 읽는다
  • 단 )-괄호가 있으면 우선순위 가 있으므로 왼쪽으로 읽는다 그러고 오른쪽으로 도착하면 나머지를 왼쪽으로 읽는다
  • 영어로 읽으면 편하다
    . pointer to : *
    . [n] : n array of
    . (type):function (has type parameter) return
1.
int num[3];
num(식별자)>>[3]>>int 순서대로 읽음
num is 3 array of int
num은 3개의 원소를 가진 배열, 원소의 타입은 정수이다

2.
int *num[3];
num>>[3]>>*>>int
num is 3 array of pointer to int 

3.
int (*num)[3]{주소명};
num>>)>>(*)>>[3]>>int
num is pointer to 3 array of int
넘은 포인터이다.정수 3개가 들어있는 배열에 대한 포인터이다.
넘은 포인터인데 포인터가 가리키는 대상이 정수 3개가 들어있는 배열이다 라는 뜻

4.
const int * const ptr;
ptr>>const>>*>>int>>const
ptr is const pointer to int const
ptr은 상수이다. 상수 정수를 가리키는 포인터인.

5.
int* (*(*p1)(int))[10];
p1>>*>>(int)>>*>>[10]>>*>>int
p1 is pointer to function hasint return pointer to 10 array of pointer to int
???????????????????
핵심은 p1은 포인터인데 함수를 가리키는 포인터이다.
그 함수는 int가 있고 원소가 포인터인 인티저를 가리키는 10개워 원소를 가진 배열을 리턴하는?
핵심은 함수를 가리키는 포인터라는 뜻 

6.
int* (*(*arr[5])())()
arr>>[5]>>*>>()>>*()>>*>>int
arr is 5-array of(핵심정보) pointer to function return pointer to function return pointer to int

사칙연산은 사람이 하듯 왼쪽부터 읽어나감
1+2+3;
1+2 먼저 3+3;


2차원 배열 포인터 문법

그러면 컴파일러처럼 읽기 방법을 사용해서 포인터로 이차원 배열을 표기하면

int array2[2][3];
int (*pp)[3]{array2};

int array3[2][3][4];
int(*ppp)[3][4]{array3}; 
//포인터인데 가리키는 대상이 [3][4]

int array4[2][3][4][5]; 
//배열을 포인터로 치환하면됨
int(*pppp)[3][4][5]{ array4 };
profile
공부 기록용

0개의 댓글