산업 제조
산업용 사물 인터넷 | 산업자재 | 장비 유지 보수 및 수리 | 산업 프로그래밍 |
home  MfgRobots >> 산업 제조 >  >> Industrial programming >> C 언어

C의 포인터와 다차원 배열 마스터하기

C 언어에서 배열은 연속적인 메모리 위치에 저장된 유사한 유형의 값 모음입니다. 배열(1차원 또는 다차원)의 각 요소는 하나 이상의 고유한 정수 인덱스로 식별됩니다.

반면에 포인터는 변수의 주소를 저장합니다. 배열의 0번째 요소의 주소는 배열의 포인터입니다. 포인터가 참조하는 값에 접근하려면 "역참조 연산자"를 사용할 수 있습니다.

C에서는 1차원, 2차원 또는 다차원 배열을 선언할 수 있습니다. "차원"이라는 용어는 컬렉션의 요소를 식별하는 데 필요한 인덱스 수를 나타냅니다.

포인터와 1차원 배열

1차원 배열에서 각 요소는 단일 정수로 식별됩니다.

int a[5] = {1, 2, 3, 4, 5};

여기서 숫자 "1"은 0번째 인덱스에 있고 "2"는 인덱스 1에 있는 식입니다.

0번째 요소의 주소를 저장하는 변수는 해당 요소의 포인터입니다.

int *x = &a[0];

간단히 말해서 배열의 이름도 0번째 요소의 주소를 가리킵니다. 따라서 다음 표현식을 사용할 수도 있습니다. −

int *x = a;

포인터 값은 데이터 유형의 크기만큼 증가하므로 "x++"는 포인터를 배열의 다음 요소로 이동합니다.

#include <stdio.h>
int main(){
 int arr[] = {1, 2, 3, 4, 5};
 int length = sizeof(arr) / sizeof(arr[0]);
 int i = 0;
 int *ptr = arr;
 while (i < length){
 printf("arr[%d]: %d \n", i, *(ptr + i));
 i++;
 }
 
 return 0;
}

출력

이 코드를 실행하면 다음과 같은 출력이 생성됩니다.

arr[0]: 1
arr[1]: 2
arr[2]: 3
arr[3]: 4
arr[4]: 5

포인터와 2차원 배열

1차원 배열이 요소 목록과 같다면 2차원 배열은 테이블이나 행렬과 같습니다.

2D 배열의 요소는 행과 열로 논리적으로 배열된 것으로 간주할 수 있습니다. 따라서 모든 요소의 위치는 행 번호와 열 번호라는 두 개의 인덱스로 결정됩니다. 행과 열 인덱스는 모두 "0"부터 시작합니다.

int arr[2][2];

이러한 배열은 -

로 표시됩니다. <일> 열0 열1 콜2 Row0arr[0][0]arr[0][1]arr[0][2]Row1arr[1][0]arr[1][1]arr[1][2]Row2arr[2][0]arr[2][1]arr[2][2]

표 형식의 배열은 단지 논리적 표현일 뿐이라는 점에 유의할 수 있습니다. 컴파일러는 연속 바이트 블록을 할당합니다. C에서 배열 할당은 행 중심 방식으로 수행됩니다. 즉, 요소를 행 방식으로 배열로 읽어옵니다.

여기서는 3개 행과 4개 열(첫 번째 대괄호 안의 숫자는 항상 행 수를 나타냄)로 구성된 2D 배열을 −

로 선언합니다.
int arr[3][4] = {
 {1, 2, 3, 4},
 {5, 6, 7, 8},
 {9, 10, 11, 12}
};

컴파일러는 행 방향 순서로 위의 2D 배열에 대한 메모리를 할당합니다. 배열의 첫 번째 요소가 주소 1000에 있고 "int" 유형의 크기가 4바이트라고 가정하면 배열의 요소는 다음과 같은 할당된 메모리 위치를 갖게 됩니다. −

<일> 행 0 행 1 행 2 값123456789101112주소100010041008101210161020102410281032103610401044

&연산자의 주소를 사용하여 배열 num의 첫 번째 요소의 주소를 포인터 ptr에 할당합니다.

int *ptr = &arr[0][0];

예시 1

포인터가 1씩 증가하면 다음 주소로 이동합니다. "34" 배열의 모든 12개 요소는 다음과 같이 루프에서 액세스할 수 있습니다. −

#include <stdio.h>
int main(){
 int arr[3][4] = {
 {1, 2, 3, 4},
 {5, 6, 7, 8},
 {9, 10, 11, 12},
 };
 // pointer ptr pointing at array num
 int *ptr = &arr[0][0];
 int i, j, k = 0;
 // print the elements of the array num via pointer ptr
 for (i = 0; i < 3; i++){
 for (j = 0; j < 4; j++){
 printf("%d ", *(ptr + k));
 k++;
 }
 printf("\n");
 }
 
 return 0;
}

출력

이 코드를 실행하면 다음과 같은 출력이 생성됩니다.

1 2 3 4 
5 6 7 8 
9 10 11 12

일반적으로 배열 요소의 주소는 다음 공식을 사용하여 −

add of element at ith row and jth col = baseAddress + [(i * no_of_cols + j) * sizeof(array_type)]

34개 배열에서는

add of arr[2][4] = 1000 + (2*4 + 2)*4 = 1044

위 그림을 보면 "arr[3][4]"의 주소가 1044인 것을 확인할 수 있습니다.

예시 2

역참조 포인터를 사용하여 주소의 값을 가져옵니다. 이 공식을 사용하여 포인터의 도움으로 배열을 탐색해 보겠습니다.

#include <stdio.h>
int main(){
 // 2d array
 int arr[3][4] = {
 {1, 2, 3, 4},
 {5, 6, 7, 8},
 {9, 10, 11, 12}
 };
 int ROWS = 3, COLS = 4;
 int i, j;
 // pointer
 int *ptr = &arr[0][0];
 // print the element of the array via pointer ptr
 for (i = 0; i < ROWS; i++){
 for (j = 0; j < COLS; j++) {
 printf("%4d ",*(ptr + (i * COLS + j)));
 }
 printf("\n");
 }
 
 return 0;
}

출력

이 코드를 실행하면 다음과 같은 출력이 생성됩니다.

 1 2 3 4
 5 6 7 8
 9 10 11 12

포인터와 3차원 배열

3차원 배열은 2차원 배열의 배열입니다. 이러한 배열은 세 개의 첨자로 선언됩니다 -

int arr [x] [y] [j];

이 배열은 "x"개의 테이블 레이어로 간주될 수 있으며, 각 테이블에는 "x"개의 행과 "y"개의 열이 있습니다.

3D 배열의 예는 다음과 같습니다. -

int arr[3][3][3] ={
 { {11, 12, 13}, {14, 15, 16}, {17, 18, 19} },
 { {21, 22, 23}, {24, 25, 26}, {27, 28, 29} },
 { {31, 32, 33}, {34, 35, 36}, {37, 38, 39} },
};

3D 배열에 대한 포인터는 -

로 선언될 수 있습니다.
int * ptr = &arr[0][0][0];

배열 이름 자체가 0번째 요소의 주소라는 것을 알면 3D 배열의 포인터를 −

로 쓸 수 있습니다.
int * ptr = arr;

"x" 행과 "y" 열의 각 레이어는 −

를 차지합니다.
x * y * sizeof(data_type) 

바이트 수. 위에서 선언한 3D 배열 "arr"에 할당된 메모리가 주소 1000부터 시작한다고 가정하면, 두 번째 계층("i =1")은 1000 + (3 3) 4 =1036바이트 위치에서 시작됩니다.

ptr = Base address of 3D array arr 

JMAX가 행 수이고 KMAX가 열 수인 경우 첫 번째 슬라이스의 0번째 행과 0번째 열에 있는 요소의 주소는 −

입니다.
arr[1][0][0] = ptr + (1 * JMAX * KMAX)

i번째 슬라이스의 j번째 행과 k번째 열에 있는 요소의 값을 구하는 공식은 다음과 같습니다. -

arr[i][j][k] = *(ptr + (i * JMAX*KMAX) + (j*KMAX + k))

예:포인터 역참조를 사용하여 3D 배열 인쇄

이 공식을 사용하여 포인터 역참조를 통해 3D 배열을 인쇄해 보겠습니다. −

#include <stdio.h>
int main(){
 int i, j, k;
 int arr[3][3][3] = {
 { {11, 12, 13}, {14, 15, 16}, {17, 18, 19} },
 { {21, 22, 23}, {24, 25, 26}, {27, 28, 29} },
 { {31, 32, 33}, {34, 35, 36}, {37, 38, 39} },
 };
 int JMAX = 3, KMAX = 3;
 int *ptr = arr; // &arr[0][0][0];
 for(i = 0; i < 3; i++){
 for(j = 0; j < 3; j++){
 for(k = 0; k < 3; k++){
 printf("%d ",*(ptr+(i*JMAX*KMAX)+(j*KMAX+k)));
 }
 printf("\n");
 }
 printf("\n");
 }
 
 return 0;
}

출력

이 코드를 실행하면 다음과 같은 출력이 생성됩니다.

11 12 13 
14 15 16 
17 18 19 
21 22 23 
24 25 26 
27 28 29 
31 32 33 
34 35 36 
37 38 39

일반적으로 포인터를 사용하여 배열에 액세스하는 것은 아래 첨자 표현을 사용하여 배열에 액세스하는 것과 매우 유사합니다. 둘 사이의 주요 차이점은 배열의 첨자 선언은 메모리를 정적으로 할당하는 반면 동적 메모리 할당에는 포인터를 사용할 수 있다는 것입니다.

다차원 배열을 함수에 전달하려면 아래 첨자 대신 포인터를 사용해야 합니다. 그러나 첨자 배열을 사용하는 것이 포인터를 사용하는 것보다 더 편리하므로 초보자에게는 어려울 수 있습니다.


C 언어

  1. C의 포인터:C 프로그래밍의 포인터란 무엇입니까? 유형
  2. C++의 데이터 캡슐화
  3. 동적 데이터 처리를 위해 C 구조의 유연한 배열 멤버 마스터하기
  4. C 프로그래밍의 사용자 정의 함수 유형
  5. C++ 생성자를 사용하여 동적 초기화 마스터하기
  6. C - 연산자
  7. Windows에서 C++ IDE를 다운로드하고 설치하는 방법
  8. C++ 포인터와 배열
  9. C++ 연산자 오버로딩
  10. C++ 신호 처리