/C
📌 포인터와 배열의 관계
- 배열의 이름은 상수라는 점을 제외하면 포인터와 동일하다. 때문에 배열의 이름은 포인터 상수이다.
#include <stdio.h>
int main(void)
{
int arr[3] = {10, 20, 30}; // 배열 선언
int* ptr_arr = arr; // 포인터에 배열의 이름을 대입함
printf("배열의 이름을 이용하여 배열 요소에 접근 : %d %d %d\n", arr[0], arr[1], arr[2]);
printf(" 포인터를 이용하여 배열 요소에 접근 : %d %d %d\n", ptr_arr[0], ptr_arr[1], ptr_arr[2]);
printf("배열의 이름을 이용한 배열의 크기 계산 : %d\n", sizeof(arr));
printf(" 포인터를 이용한 배열의 크기 계산 : %d\n", sizeof(ptr_arr));
return 0;
}
위의 예시 코드에서 포인터를 이용한 크기를 계산할 때, 포인터 변수 자체의 크기가 출력되는 것에 유의해야 한다.
- 배열의 포인터 연산
int arr[3] = {10, 20, 30}; //배열 선언
printf("%d, %d, %d \n", *(arr+0), *(arr+1), *(arr+2)); //10, 20, 30
위의 예시 코드처럼 배열의 이름을 통해 포인터 연산을 하여 배열 요소에 접근할 수 있다. 따라서 배열의 이름과 포인터 사이에는 다음과 같은 공식이 성립함을 알 수 있다.
//arr이 배열의 이름이거나 포인터이고 n이 정수일 때
arr[n] == *(arr+n)
📌 포인터 배열과 배열 포인터
- 포인터 배열은 배열 요소로 포인터 변수를 갖는 배열이다. 반면 배열 포인터는 배열을 가리킬 수 있는 포인터를 말한다. 이는 2차원 이상의 배열을 가리킬 때 포인터를 통해 배열과 같은 인덱싱을 하도록 한다. 즉, 포인터를 배열처럼 사용하기 위해 배열 포인터를 활용한다.
포인터 배열의 예시 코드를 살펴보자.
#include <stdio.h>
int main(void)
{
int i, arr_len;
int num01 = 10, num02 = 20, num03 = 30;
int* arr[3] = {&num01, &num02, &num03}; // int형 포인터 배열 선언
arr_len = sizeof(arr)/sizeof(arr[0]);
for (i = 0; i < arr_len; i++)
{
printf("%d\n", *arr[i]);
}
return 0;
}
//10
//20
//30
위의 예시가 메모리 상에서 작동되는 방식은 아래와 같다.
배열 포인터의 예시 코드를 살펴보자.
#include <stdio.h>
int main(void)
{
int arr[2][3] =
{
{10, 20, 30},
{40, 50, 60}
};
printf("%d\n", *arr[0]);
printf("%d\n", *arr[1]);
return 0;
}
//10
//40
- 2차원 배열에서는 행의 길이가 부분 배열의 크기를 의미한다.
sizeof(arr[0])/sizeof(타입)
- int arr[2][3]에서 포인터 연산 시 증감하는 값의 크기는 Int형 데이터 타입의 크기인 4바이트에 배열 행의 길이인 3을 곱한 12바이트가 된다. 이때 배열 arr을 가리키는 포인터를 선언하는 방식은 아래와 같다.
int (*pArr)[3];
- 포인터 배열과 배열 포인터를 구분할 수 있어야 한다.
int (*pArr)[3];
위의 코드는 int형 데이터를 저장할 수 있는 2차원 배열을 가리키는 포인터이고
int *pArr[3];
위의 코드는 int형 데이터를 가리킬 수 있는 포인터 변수를 모아놓은 배열을 가리키는 포인터 배열이다. (말이 어렵네요)
- main함수는 C에서 가장 먼저 호출되는 함수이다. 함수이기에 마찬가지로 인수를 전달받거나 반환값을 갖는 것이 가능하다.