본문 바로가기
C/기초(두들낙서)

[C기초] 배열 포인터

by Meaning_ 2022. 1. 2.
728x90
반응형

배열과 덧셈의 교환법칙

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
 
#include <stdio.h>
#include<string.h>
 
int main() {
 
    int arr[3= { 1,2,3 };
    int* ptr = arr;
 
 
    for (int i = 0; i < 3; i++) {
        printf("%d ", i[ptr]);
    }
    
}
cs

 

i[ptr]의 정체는 무엇일까??

c언어에서는 a[b]=*(a+b)로 처리한다.

arr[i]==*(arr+i)==*(ptr+i)==*(i+ptr) ==i[ptr]이 된다.

 

그렇기에 출력값은 1,2,3이 된다. 

 

배열 포인터를 들어가기 전 중요한것 세가지를 짚고 넘어가려한다.

 

1. ptr==&ptr[0]

2. *ptr==ptr[0]

3. ptr+1 = ptr에 sizeof(*ptr)을 더한 값

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
 
#include <stdio.h>
#include<string.h>
 
int main() {
 
    
    int arr[3= { 1,2,3 };
    printf("arr=%d\n", arr);
    printf("arr+1=%d\n", arr + 1);
    printf("&arr=%d\n"&arr);
    printf("&arr+1=%d\n"&arr + 1);
 
 
}
 
cs

왜 &arr+1을 했을 때 12바이트가 더해졌을까?

아까 중요한것 중 3번인 ptr+1은 ptr에  sizeof(*ptr)을 적용해보면,

&arr+1은 &arr에 sizeof(arr)이 더해진 값이라고 생각할 수 있다. 

이걸 시각화해보면 

배열을 가리키는 포인터가 1을 더했다는 것은 다음배열로 넘어간다는 것을 의미한다. 

 

배열 포인터

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <stdio.h>
#include<string.h>
 
int main() {
 
    int arr[3= { 1,2,3 };
    int(*ptr_arr)[3]; //길이 3인 int형 배열을 가리키는 포인터 선언
    ptr_arr = &arr;//배열의 주소값 집어넣음
 
    for (int i = 0; i < 3; i++) {
        printf("%d\n", (*ptr_arr)[i]);
    }
}
 
cs

 

printf("%d\n", (*ptr_arr)[i]);

--> 출력값이 1 2 3 으로 나오는데

포인터가 arr을 가리키는 상태에서(ptr_arr이 가리키는 변수) arr[i]를 출력하라는 의미이다. 

 

배열 포인터와 포인터 배열의 차이 

 

포인터 배열

 

포인터 배열은 포인터를 원소로 갖는 배열을 의미한다. 포인터 각각을 배열로 표현한 것.

 

1
2
3
4
5
6
7
8
int main() {
 
    int a = 10;
    int b = 20;
    int c = 30;
 
    int* arr[3] = { &a,&b,&c };
}
cs

 

자료형 * 배열의이름[배열의 크기] <-- 이 형태로 선언한다. 

arr[0]을 출력하면 a의 주소값이 나온다.

 

int *arr[3]은 메모리 3곳을 가리키는 배열이라 할 수 있다.

 

배열 포인터

배열 포인터는 배열을 가리키는 하나의 포인터를 의미한다.

당연한 말이겠지만 배열포인터는 배열만 가리킬 수 있다.

 

int (*arr)[3] <--이런식으로 선언한다. 

이는 길이 3을 갖는 int형 배열만 가리킬 수 있다. 

 

포인터 배열은 포인터가 여러개 모여서 배열을 이룬것 , 배열 포인터는 배열을 가리키는 하나의 포인터를 의미한다. 

 

참고자료

https://wonit.tistory.com/527

 

[C 언어] 포인터로 2차원 배열 다루기 (주소 접근 및 원소 값 접근)

2차원 배열의 형태 우리가 2차원 배열과 포인터에 대한 상관관계를 파악하고 조작하기 위해서는 2차원 배열이 메모리에 어떻게 저장되는지 알아야 한다. 다음과 같은 배열이 존재한다고 가정해

wonit.tistory.com

https://blockdmask.tistory.com/56

 

[C언어] 배열포인터, 포인터배열 정리 (pointer)

안녕하세요! BlockDMask 입니다 오늘은 많이들 햇갈려 하는 array pointer pointer array pointer pointer array array pointer. C언어의 포인터 개념과 배열 개념을 조금은 알고 계셔야 내용을 이해할 수 있을..

blockdmask.tistory.com

2차원 배열과 배열 포인터 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
 
#include <stdio.h>
#include<string.h>
 
int main() {
 
    int arr[2][3= {
        {1,2,3},
        {4,5,6}
    };
    printf("%d\n"sizeof(arr));
    printf("%d\n"sizeof(arr[0]));
    printf("%d\n",sizeof(arr[0][0]));
 
 
 
}
 
cs

 

첫번째 출력값은 arr의 크기이므로 4바이트 *6 이기에 24

두번째 출력값은 arr의 0번째 행을 하나의 배열로 보기때문에 4바이트 *3 을 해서 12

마지막 출력값은 4이다. 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <stdio.h>
#include<string.h>
 
int main() {
 
    int arr[2][3= {
        {1,2,3},
        {4,5,6}
    };
    
 
    //주소값은 다 같음
    printf("%d\n"&arr);//
    printf("%d\n",&arr[0]);//
    printf("%d\n"&arr[0][0]);//
 
  
 
}
cs

 

여기서는 세개의 출력값이  다 같은 숫자이다. 

그 이유는 결국 주소의 대표값인 arr[0]만 나오기 때문이다. 

각각의 원소가 100번지부터 120번지 해당될 때 결국 주소값은 대표값인 100번지만 나온다고 생각하면 된다.

 

 

++) 왜 0번째 행이 전체행을 대표하게 된걸까 궁금할 수 있는데

예를 들어 int arr[10]의 배열에서 arr이 0번째 칸의 주소가 되듯

이차원 배열  int arr[10][10] 에서도 배열의 이름인 arr이 0번째 행의 주소 &arr[0] 를 의미하기에 대표값인 0번째 행만 나온다고 말하는 것이 그 의미이다.

 

 

 

이제 배열 포인터를 선언해 보겠다. 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
int main() {
 
    int arr[2][3= {
        {1,2,3},
        {4,5,6}
    };
    //arr=&arr[0]
    //*ptr=arr[0]
    //ptr+1=ptr에 sizeof(*ptr)더한 값
 
 
    int(*ptr)[3= arr; //int(*ptr)[3]=&arr[0] arr[0]행의 주소값 들어감
 
    for (int i = 0; i < 2; i++) {
        for (int j = 0; j < 3; j++) {
            printf("%d ", ptr[i][j]);
        }
        printf("\n");
    }
}
cs

 

어떻게 ptr이 arr처럼 기능할 수 있을까?

 

ptr이 arr로 대체되는지 알아보기 위해 

1)ptr[i]==arr[i]

2)ptr[i][j]==arr[i][j]

3)ptr==arr 

이 세가지를 살펴볼 것이다.

 

 

ptr=arr이라는 것은 ptr=&arr[0] 와 같다. 즉 ptr은 arr[0]을 가리키고 있다 

 

*(ptr+i) 를 하면 전체 주소값이 12i(12바이트가 더해짐, 즉 arr[0]의 크기가 12이기 때문에 12i만큼 더해진다고 생각하면됨) 가 더해진다.

 

예를 들어 *(ptr+1)을 하면 arr[1]을 가리키기에 ptr에 1을 더한다는 것은 다음행으로 넘어간다고 봐도 무방하다.

 

ptr+i는 arr[i]를 가리키고 있기에  *(ptr+i)==arr[i]라는 것을 알 수 있다 그래서 1번째 조건인 ptr[i]==arr[i]를 만족시킨다고 할 수 있다. 

cf) *(a+b) 는 a[b]이기에 ptr[i]=arr[i]이 되므로 ptr[i]==arr[i]라는 1번째 조건을 만족하는 것을 알 수 있다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <stdio.h>
#include<string.h>
 
int main() {
 
    int arr[2][3= {
        {1,2,3},
        {4,5,6}
    };
 
 
 
    for (int(*row)[3= arr; row < arr + 2; row++) {
        for (int* col = *row; col < *row + 3; col++) {
            printf("%d "*col);
        }
        printf("\n");
    }
    
}
 
cs

 

저 해괴한(?) for문을 돌렸을 때 배열의 원소가 잘 출력되는데 어떻게 된 것일까??

 

int (*row)[3]=arr; 이라는 것은

 

 

row가 arr의 0행을 가리키는 것을 의미한다.

row++은  row+1을 의미하는데, 다음 행(배열)을 가리키는 것을 의미한다. 

row<arr+2라는 것은 arr[2]의 전까지 돌리겠다는 것을 의미한다.

 

col은 *row인데 *row는 row가 가리키는 배열 자체를 의미한다.

예를 들어 row가 위의 사진처럼 arr[0]을 가리킬때 

int *col=*row라는 것은 

col에는  arr[0]이라는 배열의 0번째 주소값이 들어감을 의미한다. 그래서 arr[0][0]을 가리킨다고 보면된다.

그냥 *row가 arr[0]이라는 배열 자체라고 생각하면 된다.

(ptr=arr 일 떄 ptr에 &arr[0]이 들어가는 것과 같은 원리)

 

arr[0]을 자세히 보면

 

즉 col에는 &(*row)[0]이 들어간다. 

 

 

 

728x90
반응형

'C > 기초(두들낙서)' 카테고리의 다른 글

[C기초] 포인터와 배열 연습문제  (0) 2022.01.08
[C기초] 포인터 배열  (0) 2022.01.04
[C 백준] 브론즈 3/ 세 수  (0) 2022.01.02
[C기초] 포인터 /포인터와 배열  (0) 2022.01.02
[C기초] 배열과 문자열  (0) 2022.01.02

댓글