지난 시간 1차원 배열 포인터를 배웠다면
https://accompani-i.tistory.com/206
이번 시간에는 2차원 배열과 포인터를 학습해보자.
ex. int a[3][2] = {{1,2},{3,4},{5,6}};
a에는 배열의 첫 번째 주소값이 들어가므로, 100이 들어가고
a | 배열 | 행을 대표하는 번지 수 | 배열의 값[임의의 번지수] | 배열의 값[임의의 번지수] | |
100번지 | a[0] | 100번지 | 1[100번지] | 2[101번지] | |
a[1] | 102번지 | 3[102번지] | 4[103번지] | ||
a[2] | 104번지 | 5[104번지] | 6[105번지] |
여기서 1차원 배열과 차이점은 각 행을 대표하는 번지 수가 있다.
각 행을 대표하는 번지수는 각 배열의 첫 번째 값의 번지수와 같다
지금까지 배운 배열과 포인터를 간략하게 표현하면,
배열(a) 자체를 대표하는 주소가 있고(위에서 a=100)
2차원 배열에서는 행(a[0])을 대표하는 주소가이 있고(100번지, 102번지, 104번지)
배열의 각각의 값에는 각각의 값마다 주소가 있다.(100번지~105번지)
printf("%d₩n",a); = 100
주의1
printf("%d₩n", *a); = 100
1차원 배열에서 *a는 'a의 값'으로 참조하고 있는 주소의 값을 반환했는데,
여기서는 참조하고 있는 것이 값 자체 가 아니고 주소를 참조하고 있기 때문에, 1이 아니고 행의 대표주소인 100을 출력하게 된다.
주의2
printf("%d₩n", **a) = 1
여기에서는 쉽게 **a는 'a의 값의 값'으로 생각 하면 되는데, a가 참조하고 있는 행이 다시 참조 하고 있는 값 즉 1이 반환된다.
ex.
#include<stdio.h>
int main() {
int data[][3] = {1,3,4,5,2,9,6,8,7};
int *p = data[1];
int x,y;
x = *p;
y = *(p+2);
printf("x=%d, y=%d₩n", x,y);
}
해설
data[][3]은 어렵게 생각하지 말고 3열로 맞추면 알아서 []가 채워진다. 고로 3행 3열짜리 배열이 완성된다.
p | data배열 | 행 대표 번지수 | 배열의 값[임의의 번지수] | 배열의 값[임의의 번지수] | 배열의 값[임의의 번지수] |
100번지 | data[0] | 100번지 | 1[100번지] | 3[101번지] | 4[102번지] |
data[1] | 103번지 | 5[103번지] | 2[104번지] | 9[105번지] | |
data[2] | 106번지 | 6[106번지] | 8[107번지] | 7[108번지] |
배열을 위 표처럼 세팅해놓고 시작하면 된다.
int *p = data[1];
int x,y;
x = *p;
y = *(p+2);
*p | x= *p | y = *(p+2) |
배열의 2번째 번지수를 참조하므로 | *p = p주소의 값이므로 103번지의 값인 5 |
p는 103이고 p+2는 105이므로 105번지의 값인 9를 출력한다. |
103 |
답 5,9
여어어어기에서의 주의1
*p가 위에 배운 것처럼 2차원 배열일 경우 번지수를 참조하는 경우 아닌가욧???????????
그래서 번지수의 값이 아니고 103,105를 출력해야 되는 거 아닌가욧?!!!?!?!?!?
3,9를 출력하려면 **p, **(p+2)여야 하는 것이 아닌가욧?!!?!?!!?
헷갈릴 수 있는 부분인데, 무엇을 참조하느냐가 관건이다...
제일 상단에서의 참조 순서는 a->행의 대표 주소->배열의 대표 주소로 참조하기 때문에
*a가 무얼 참조하느냐 : 행의 대표주소를 참조합니다.
**a가 무얼 참조하느냐: *(행의 대표주소를 참조합니다.) -> 행의 대표주소의 값은 무엇이냐 -> (*a)의 값을 참조합니다.
이런 연산 결과가 펼쳐지는 것이고
위 예제에서는
이미 행의 대표 주소 중 하나를 참조하고 있으므로, *p는 그 주소의 값을 출력하라는 의미이다
여어어어기에서의 주의2
선언하는 것과 주소의 값을 출력하는 것의 차이
포인터 변수의 '선언'
int *p -> p는 포인터 변수야.
x=*p -> p가 참조하고 있는 값을 x에 할당해라.
주의 1과 2를 주의깊게 잘 읽어보도록 하자.
ex.
#include<stdio.h>
int main() {
int darr[3][3] = {{1,2,3}, {4,5,6}, {7,8,9}};
int sum1, sum2;
sum1 = *(*darr+1) + *(*darr+2);
sum2 = *darr[1] + *darr[2];
printf("%d, %d", sum1, sum2);
}
해설
위 2차원 배열을 표로 표현하면
darr | darr배열 | 행 대표 번지수 | 배열의 값[임의의 번지수] | 배열의 값[임의의 번지수] | 배열의 값[임의의 번지수] | |
100번지 | darr[0] | 100번지 | 1[100번지] | 2[101번지] | 3[102번지] | |
darr[1] | 103번지 | 4[103번지] | 5[104번지] | 6[105번지] | ||
darr[2] | 106번지 | 7[106번지] | 8[107번지] | 9[108번지] |
먼저 sum1,sum2가 무엇을 의미하는지 파악해보면
sum1 = *(*darr+1) + *(*darr+2) -> darr이 참조하는 값+ 1 값이 참조하는 값 + darr이 참조하는 값 +2가 참조하는 값
sum2 = *darr[1] + *darr[2] -> darr[1] 행 대표 번지가 참조하는 값 + darr[2] 행 대표 번지가 참조하는 값
sum1 = *(*darr+1) + *(*darr+2) | sum2 = *darr[1] + *darr[2] |
*(*darr+1) -> *(*100+1 번지) ->*(101) -> 101번지의 값 -> 2 | *darr[1] ->103번지의 값 ->4 |
*(*darr+2) -> *(*100+2번지) -> *(103) -> 103번지의 값-> 3 | *darr[2] ->106번지의 값->7 |
2+3 = 5 | 4+7 = 11 |
*(*darr+1)은 정확히 darr의 값이므로 행 대표 번지수의 첫 번째 주소인 100번지를 참조한다.(darr의 주소인 100이 아니다)
'iOS > 정보처리기사' 카테고리의 다른 글
[정보처리기사] C언어 - 구조체, 포인터 구조체.. (0) | 2022.06.17 |
---|---|
[정보처리기사] C언어 - 포인터 배열(배열 포인터와 포인터 배열 차이) feat. 문제로 강화하기 (0) | 2022.06.13 |
[정보처리기사] C언어 - 배열과 포인터(배열에도 주소값이 있다) (0) | 2022.06.10 |
[정보처리기사] C언어 - scanf 와 변수(feat. 포인터 변수) (0) | 2022.06.09 |
[정보처리기사] C언어 - 포인터의 이해(feat. 포인터변수, 주소, 주소값) (0) | 2022.06.09 |