티스토리 뷰

2021.02.23.화
배열의 주소

✔ 배열은 같은 자료형의 변수를 메모리를 연속으로 할당한다.
✔ 그러므로 배열의 요소들은 일정한 간격으로 주소를 갖게 되는데, 이는 자료형의 크기와 같다.
✔ 만약 배열 arr가 100번지부터 할당된다면, arr[0]은 100~103번지를 가지고 arr[1]은 104~107번지를 가진다.
✔ 배열의 요소는 위와같이 자료형과 같은 크기의 공간을 할당받게되고, 그 첫번째 공간의 주소가 곧 요소의 주소가 된다.
✔ 그리고 배열은 할당 받은 전체 공간의 첫번째 메모리의 주소를 가지게 된다.
✔ 결국 배열의 첫번째 요소의 주소를 알게되면, 배열의 주소뿐만 아니라 다른 요소의 주소도 쉽게 알 수 있다.
#include <stdio.h>
int main(void){
int arr[3];
printf("배열의 주소 : %p\n", arr);
printf("첫번째 요소의 주소 : %p\n", &arr[0]);
printf("두번째 요소의 주소 : %p\n", &arr[1]);
printf("세번재 요소의 주소 : %p\n", &arr[2]);
}

✔ 주소를 출력할 수 있는 형식지정자 %p와 주소연산자 &를 사용해서 배열과 배열의 요소들의 주소를 확인할 수 있다.
✔ 배열명은 곧 주소를 의미하므로 주소연산자 & 가 필요 없다.
✔ 주소를 확인하면 요소의 주소가 자료형의 크기만큼 차이가 발생하는 것을 확인할 수 있다.
주소값의 연산
주소 ± 정수 → 주소 ± (정수*변수 자료형의 크기)
✔ 주소는 자료형의 크기만큼 차이를 가지므로, 주소를 연산하여 배열의 다음 요소에 접근할 수 있지 않을까?
✔ 매 번 자료형의 크기만큼 주소 값에 더하거나 뺄 수 없으므로, 주소의 연산은 위와 같은 방식으로 진행된다.
int arr[3] = { 1, 2, 3 };
*(arr + 0) == arr[0] //1
*(arr + 1) == arr[1] //2
*(arr + 2) == arr[1] //3
✔ 배열 자체의 주소에 1을 더했다는 것은 사실 1*변수 자료형의 크기임으로
✔ 배열의 주소를 100이라고 가정했을 때, 100 + ( 1 * 4byte ) 가 된다. 즉 arr[1]의 주소인 104가 된다.
✔ 이렇게 주소값의 연산과 간접 참조 연산자 *을 사용해 배열의 다른 요소에 접근할 수 있다.
✔ 주소값의 뺄셈도 같은 원리로 진행된다.
int arr[3] = { 1, 2, 3 };
int *p = &arr[2];
*(p - 0) == arr[2] //3
*(p - 1) == arr[1] //2
*(p - 2) == arr[0] //1
✔ 만약 소괄호가 없다면, 간접 참조 연산자 * 을 사용해 접근한 주소에 저장된 값과 연산이 되므로 주의하자.
int arr[3] = { 1, 2, 3 };
int *p = &arr[2];
*p - 0 == 1 - 0 //1
*p - 1 == 1 - 1 //0
*p - 2 == 1 - 2 //-1
배열명의 역할을 하는 포인터
int arr[3] = { 1, 2, 3 };
int *p = arr;
p[0] == arr[0]
p[1] == arr[1]
p[2] == arr[2]
✔ 배열명은 곧 주소를 의미하므로 포인터에 저장할 수 있고, 이런 경우는 대괄호를 사용해 배열과 같이 표현할 수 있다.
✔ 배열과 같이 표현할 수 있으므로 for문을 사용해 배열의 요소에 접근할 수 있다.
#include <stdio.h>
int main(void)
{
int arr[5] = { 1, 2, 3, 4, 5 };
int * p = arr;
for(int i=0; i<5; i++){
printf("%d ",*(p+i));
printf("%d \n",p[i]);
}
return 0;
}
/*
실행결과
1 1
2 2
3 3
4 4
5 5
*/
배열명, 포인터와 매개변수
✔ 포인터 변수에 배열의 주소를 저장하고, 함수의 매개 변수로 받게 된다면 함수에서 main 함수의 배열의 값에 접근할 수 있다.
✔ 하지만 배열을 직접 매개변수로 전달하는 경우에도 주소값이 전달된다.
✔ 배열을 매개변수로 사용해도 포인터로 인지하는 이유는, 배열의 길이가 길어지면 저장된 값이 많아지므로 복사해 사용하는 것이 비효율적이기때문에 포인터로 인지하기로 약속했기 때문이다.
✔ 배열을 직접 매개변수로 사용하는 것 보다 포인터를 사용하는 것을 추천한다.
✔ 그리고 외부에서 배열의 값을 수정할 수 있는 경우, 의도치않게 값을 변경할 수 있으므로 주의하자.
#include <stdio.h>
void test(int *p, int arr[]);
int main(void){
int arr[3] = { 1, 2, 3 };
int *p = arr;
test(p, arr);
printf("%d\n", arr[0]); //10
printf("%d\n", arr[1]); //20
printf("%d\n", arr[2]); //3
return 0;
}
void test(int *p, int arr[]){
p[0] = 10;
arr[1] = 20;
}
[참고] 한빛미디어-혼자 공부하는 C언어 유튜브 강의 / 엘리스 트랙-혼자 공부하는 C언어 / 길벗-C언어 코딩 도장 / 위키백과
'BackEnd > C' 카테고리의 다른 글
[15일차] 문자열 관련 함수의 원형 (0) | 2021.02.25 |
---|---|
[13-14일차] 문자/문자열 (0) | 2021.02.25 |
[12일차] 포인터 (0) | 2021.02.23 |
[11일차] 함수/배열 복습 (0) | 2021.02.23 |
[10일차] 제어문 복습 (0) | 2021.02.20 |