배열과 덧셈의 교환법칙
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형 배열만 가리킬 수 있다.
포인터 배열은 포인터가 여러개 모여서 배열을 이룬것 , 배열 포인터는 배열을 가리키는 하나의 포인터를 의미한다.
참고자료
[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]이 들어간다.
'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 |
댓글