logo

배열에 대한 포인터 | 배열 포인터

전제조건: 포인터 소개

다음 프로그램을 고려해보세요:








#include> int> main()> {> >int> arr[5] = { 1, 2, 3, 4, 5 };> >int> *ptr = arr;> >printf>(>'%p '>, ptr);> >return> 0;> }>



>

>

위 프로그램에는 포인터가 있습니다. ptr 0을 가리키는 말배열의 요소입니다. 마찬가지로, 배열의 한 요소 대신 전체 배열을 가리킬 수 있는 포인터를 선언할 수도 있습니다. 이 포인터는 다차원 배열에 관해 이야기할 때 유용합니다.

통사론:

data_type  (* var_name ) [size_of_array];>

여기:

    data_type은 배열이 보유하는 데이터 유형입니다. var_name은 포인터 변수의 이름입니다. size_of_array는 포인터가 가리킬 배열의 크기입니다.

int (*ptr)[10];>

여기 ptr 10개의 정수 배열을 가리킬 수 있는 포인터입니다. 첨자는 간접법보다 우선순위가 높으므로 간접법 연산자와 포인터 이름을 괄호 안에 넣어야 합니다. 여기서 ptr의 유형은 '10개의 정수 배열에 대한 포인터'입니다.

참고: 0을 가리키는 포인터배열의 요소와 전체 배열을 가리키는 포인터는 완전히 다릅니다. 다음 프로그램은 이를 보여줍니다.




// C program to understand difference between> // pointer to an integer and pointer to an> // array of integers.> #include> int> main()> {> >// Pointer to an integer> >int> *p;> > >// Pointer to an array of 5 integers> >int> (*ptr)[5];> >int> arr[5];> > >// Points to 0th element of the arr.> >p = arr;> > >// Points to the whole array arr.> >ptr = &arr;> > >printf>(>'p = %p, ptr = %p '>, p, ptr);> > >p++;> >ptr++;> > >printf>(>'p = %p, ptr = %p '>, p, ptr);> > >return> 0;> }>

>

>

산출

p = 0x7fff6463e890, ptr = 0x7fff6463e890 p = 0x7fff6463e894, ptr = 0x7fff6463e8a4>

여기, 0을 가리키는 포인터입니다배열의 요소 도착 , 하는 동안 ptr 전체 배열을 가리키는 포인터입니다. 도착 .

  • 기본 유형 int이고 기본 유형은 다음과 같습니다. ptr '5개의 정수 배열'입니다.
  • 우리는 포인터 연산이 기본 크기를 기준으로 수행된다는 것을 알고 있으므로 ptr++를 작성하면 포인터가 ptr 20바이트 앞으로 이동됩니다.

다음 그림은 포인터 p와 ptr을 보여줍니다. 더 어두운 화살표는 배열에 대한 포인터를 나타냅니다.

포인터 표현식을 역참조하면 해당 포인터 표현식이 가리키는 값을 얻습니다. 배열에 대한 포인터는 배열을 가리키므로 이를 역참조하면 배열을 가져와야 하며 배열 이름은 기본 주소를 나타냅니다. 따라서 배열에 대한 포인터가 역참조될 때마다 포인터가 가리키는 배열의 기본 주소를 얻습니다.




// C program to illustrate sizes of> // pointer of array> #include> int> main()> {> >int> arr[] = { 3, 5, 6, 7, 9 };> >int> *p = arr;> >int> (*ptr)[5] = &arr;> > >printf>(>'p = %p, ptr = %p '>, p, ptr);> >printf>(>'*p = %d, *ptr = %p '>, *p, *ptr);> > >printf>(>'sizeof(p) = %lu, sizeof(*p) = %lu '>,> >sizeof>(p),>sizeof>(*p));> >printf>(>'sizeof(ptr) = %lu, sizeof(*ptr) = %lu '>,> >sizeof>(ptr),>sizeof>(*ptr));> >return> 0;> }>

>

>

산출

p = 0x7fff55adbff0, ptr = 0x7fff55adbff0 *p = 3, *ptr = 0x7fff55adbff0 sizeof(p) = 8, sizeof(*p) = 4 sizeof(ptr) = 8, sizeof(*ptr) = 20>

다차원 배열에 대한 포인터

1. 포인터와 2차원 배열

2차원 배열에서는 두 개의 첨자를 사용하여 각 요소에 액세스할 수 있습니다. 여기서 첫 번째 첨자는 행 번호를 나타내고 두 번째 첨자는 열 번호를 나타냅니다. 2차원 배열의 요소는 포인터 표기법을 사용하여 액세스할 수도 있습니다. arr이 2차원 배열이라고 가정하면 모든 요소에 접근할 수 있습니다. 도착[i][j] 포인터 표현식을 사용한 배열 *(*(arr + i) + j) . 이제 우리는 이 표현이 어떻게 파생될 수 있는지 살펴보겠습니다.
2차원 배열을 생각해보자 도착[3][4] :

int arr[3][4] = { {1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12} };>

컴퓨터의 메모리는 선형적으로 구성되므로 2차원 배열을 행과 열로 저장할 수 없습니다. 행과 열의 개념은 이론적일 뿐이며 실제로 2차원 배열은 행 중심 순서로 저장됩니다. 즉, 행이 서로 옆에 배치됩니다. 다음 그림은 위의 2차원 배열이 메모리에 어떻게 저장되는지 보여줍니다.

각 행은 1차원 배열로 간주할 수 있으므로 2차원 배열은 차례로 배치된 1차원 배열의 모음으로 간주할 수 있습니다. 즉, 2차원 배열이 겹겹이 쌓인 것이라고 할 수 있습니다. 그래서 여기 도착 각 요소가 4개의 정수로 구성된 1차원 배열인 3개 요소의 배열입니다.
우리는 배열의 이름이 0을 가리키는 상수 포인터라는 것을 알고 있습니다.1차원 배열이며 주소 5000을 포함합니다. 이후 도착 '4개의 정수 배열에 대한 포인터'입니다. 포인터 산술에 따르면 표현식 arr + 1은 주소 5016을 나타내고 표현식 arr + 2는 주소 5032를 나타냅니다.
그래서 우리는 이렇게 말할 수 있습니다 도착 0을 가리킨다1차원 배열, 도착 + 1 1을 가리킨다1차원 배열 및 도착 + 2 2를 가리킨다nd1차원 배열.

일반적으로 다음과 같이 작성할 수 있습니다.

 arr + i Points to ith element of arr ->i번째 1차원 배열을 가리킴>
  • arr + i가 i를 가리키므로요소 도착 , 역참조하면 나는 얻을 것이다요소 도착 이는 물론 1차원 배열입니다. 따라서 표현은 *(arr + i) 우리에게 i의 기본 주소를 제공합니다1차원 배열.
  • 우리는 포인터 표현식을 알고 있습니다. *(arr + i) 아래 첨자 표현식과 동일합니다. 도착[i] . 그래서 *(arr + i) 이는 다음과 같습니다 도착[i] 우리에게 i의 기본 주소를 제공합니다1차원 배열.
  • 2차원 배열의 개별 요소에 액세스하려면 모든 j에 액세스할 수 있어야 합니다.나의 요소1차원 배열.
  • 기본형이기 때문에 *(arr + i) ~이다 정수 주소는 0입니다.나의 요소1차원 배열, i의 후속 요소의 주소를 얻을 수 있습니다.정수 값을 추가하여 1차원 배열 *(arr + i) .
  • 예를 들어 *(arr + i) + 1 1의 주소를 나타냅니다.1의 요소나의 요소1차원 배열 및 *(arr+i)+2 2의 주소를 나타냅니다.nd나의 요소1차원 배열.
  • 마찬가지로 *(arr + i) + j는 j의 주소를 나타냅니다.나의 요소1차원 배열. 이 표현식을 역참조하면 j를 얻을 수 있습니다.나의 요소1차원 배열.

포인터와 3차원 배열

int arr[2][3][2] = { {{5, 10}, {6, 11}, {7, 12}}, {{20, 30}, {21, 31}, {22, 32}} };>

3차원 배열에서는 세 개의 첨자를 사용하여 각 요소에 액세스할 수 있습니다. 3차원 배열을 살펴보겠습니다. 3차원 배열을 2차원 배열의 배열로 간주할 수 있습니다. 즉, 3차원 배열의 각 요소는 2차원 배열로 간주됩니다. 3차원 배열 도착 각 요소가 2차원 배열인 두 요소로 구성된 배열로 간주될 수 있습니다. 배열의 이름 도착 0을 가리키는 포인터이다2차원 배열.

따라서 포인터 표현식 *(*(*(arr + i ) + j ) + k)는 아래 첨자 표현식 arr[i][j][k]와 동일합니다.
우리는 *(arr + i) 표현식이 arr[i]와 동일하고 *(*(arr + i) + j) 표현식이 arr[i][j]와 동일하다는 것을 알고 있습니다. 따라서 arr[i]는 i의 기본 주소를 나타낸다고 말할 수 있습니다.2차원 배열이고 arr[i][j]는 j의 기본 주소를 나타냅니다.1차원 배열.

Java의 사용자 정의 예외

아래 예는 포인터를 사용하여 3D 배열의 요소를 인쇄하는 프로그램을 보여줍니다.




// C program to print the elements of 3-D> // array using pointer notation> #include> int> main()> {> >int> arr[2][3][2] = {> >{> >{5, 10},> >{6, 11},> >{7, 12},> >},> >{> >{20, 30},> >{21, 31},> >{22, 32},> >}> >};> >int> i, j, k;> >for> (i = 0; i <2; i++)> >{> >for> (j = 0; j <3; j++)> >{> >for> (k = 0; k <2; k++)> >printf>(>'%d '>, *(*(*(arr + i) + j) +k));> >printf>(>' '>);> >}> >}> >return> 0;> }>

>

>

산출

5 10 6 11 7 12 20 30 21 31 22 32>

다음 그림은 위 프로그램에서 사용된 3차원 배열이 메모리에 어떻게 저장되는지 보여줍니다.

배열에 대한 포인터 구독

가정하다 도착 3개의 행과 4개의 열로 구성된 2차원 배열입니다. ptr 4개의 정수 배열에 대한 포인터입니다. ptr 배열의 기본 주소를 포함합니다. 도착 .

int arr[3][4] = {{10, 11, 12, 13}, {20, 21, 22, 23}, {30, 31, 32, 33}}; int (*ptr)[4]; ptr = arr;>

부터 ptr 첫 번째 행의 2차원 배열에 대한 포인터입니다. 즉, 4개의 정수 배열입니다. ptr + 나 나를 가리킬 것이다열. 역참조 시 ptr + 나 , 우리는 i의 기본 주소를 얻습니다열. j의 주소에 접근하려면나의 요소행 포인터 표현식에 j를 추가할 수 있습니다. *(ptr + i) . 그래서 포인터 표현식은 *(ptr + i) + j j의 주소를 알려준다나의 요소행과 포인터 표현식 *(*(ptr + i)+j) j의 값을 제공합니다.나의 요소열.
우리는 포인터 표현식 *(*(ptr + i) + j)가 아래 첨자 표현식 ptr[i][j]와 동일하다는 것을 알고 있습니다. 따라서 2차원 배열의 기본 주소를 포함하는 포인터 변수가 있는 경우 해당 포인터 변수에 이중 첨자를 붙여 배열 요소에 액세스할 수 있습니다.




// C program to print elements of a 2-D array> // by scripting a pointer to an array> #include> int> main()> {> >int> arr[3][4] = {> >{10, 11, 12, 13},> >{20, 21, 22, 23},> >{30, 31, 32, 33}> >};> >int> (*ptr)[4];> >ptr = arr;> >printf>(>'%p %p %p '>, ptr, ptr + 1, ptr + 2);> >printf>(>'%p %p %p '>, *ptr, *(ptr + 1), *(ptr + 2));> >printf>(>'%d %d %d '>, **ptr, *(*(ptr + 1) + 2), *(*(ptr + 2) + 3));> >printf>(>'%d %d %d '>, ptr[0][0], ptr[1][2], ptr[2][3]);> >return> 0;> }>

>

>

산출

0x7ffc9556b790 0x7ffc9556b7a0 0x7ffc9556b7b0 0x7ffc9556b790 0x7ffc9556b7a0 0x7ffc9556b7b0 10 22 33 10 22 33>