배열은 (상수)포인터다
포인터는 배열이다 (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++:
//불가능 : 상수포인터이기 때문에
}
실제로 오류가 자주나옴
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칸 건너뛰는 것임
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개인 배열을 가리키는
}
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
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;
그러면 컴파일러처럼 읽기 방법을 사용해서 포인터로 이차원 배열을 표기하면
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 };