2026.04.12 D+41
C언어를 공부하면서 배열이랑 포인터가 계속 같이 나오는데, 처음에는 둘의 관계가 잘 이해가 안 됐다.
이번에 배열의 개념부터 주소, 포인터까지 같이 정리해봤다.
배열은 같은 타입의 데이터를 여러 개 저장하는 자료형이다.
예를 들어 정수 5개를 저장하려면:
int arr[5];
이렇게 선언한다.
int → 자료형arr → 배열 이름[5] → 원소 개수값을 넣을 때는 인덱스를 사용한다.
arr[0] = 10;
arr[1] = 20;
arr[2] = 30;
여기서 중요한 점은 인덱스는 0부터 시작한다는 것.
배열의 핵심은 메모리에 연속해서 저장된다는 점이다.
int arr[3] = {10, 20, 30};
이 배열은 메모리에 이런 식으로 저장된다.
주소 값
1000 10
1004 20
1008 30
int는 보통 4바이트즉, 배열은 중간에 끊기지 않고 이어져 있다.
이 부분이 처음에 가장 헷갈렸던 부분이다.
int arr[3] = {10, 20, 30};
여기서 arr은 단순한 변수 이름이 아니라,
첫 번째 원소의 주소처럼 동작한다.
즉,
arr == &arr[0]
라고 보면 된다.
확인 코드:
printf("%p\n", arr);
printf("%p\n", &arr[0]);
두 값이 같은 주소로 출력된다.
포인터는 주소를 저장하는 변수다.
int x = 10;
int *p = &x;
x → 값 10&x → x의 주소p → 그 주소를 저장그리고
*p
는 그 주소에 있는 값을 의미한다.
배열은 포인터와 굉장히 밀접하게 연결되어 있다.
int arr[3] = {10, 20, 30};
int *p = arr;
이 코드는 이렇게 해석된다.
int *p = &arr[0];
즉, 포인터 p는 배열의 첫 번째 원소를 가리킨다.
다음 두 코드는 같은 의미다.
arr[0]
*arr
그리고
arr[1]
*(arr + 1)
도 동일하다.
정리하면:
arr[i] == *(arr + i)
이게 배열과 포인터가 연결되는 핵심이다.
포인터는 단순히 +1을 하면 주소가 1 증가하는 게 아니라,
자료형 크기만큼 이동한다.
int *p = arr;
일 때,
p + 1
은 다음 int 위치를 가리킨다.
예:
p = 1000
p + 1 = 1004
p + 2 = 1008
이 부분도 많이 헷갈린다.
int arr[3];
→ 둘은 거의 같은 값
이건 의미가 다르다.
arr + 1 → 다음 원소
&arr + 1 → 배열 전체 크기만큼 이동
비슷해 보이지만 완전히 같지는 않다.
arr[i]
p[i]
*(arr+i)
*(p+i)
모두 동일하게 사용 가능
int arr[3];
int *p;
arr = arr + 1; // 오류
p = p + 1; // 가능
배열을 함수에 넘기면 사실상 포인터처럼 동작한다.
void printArray(int *arr, int size)
이렇게 쓰는 이유는
배열 전체가 아니라 주소만 전달되기 때문이다.
그래서 항상 크기를 같이 넘겨야 한다.
char name[6] = "hello";
메모리에는 이렇게 저장된다.
'h' 'e' 'l' 'l' 'o' '\0'
문자열은 사실 char 배열 + 끝 표시(\0) 로 구성되어 있다.
배열을 이해할 때 중요한 핵심은 2가지다.
그리고 포인터까지 연결하면:
arr == &arr[0]
*arr == arr[0]
*(arr + i) == arr[i]
이 3개를 이해하면 배열 + 포인터 구조는 거의 잡힌다.
#include <stdio.h>
int main() {
int arr[3] = {10, 20, 30};
int *p = arr;
printf("%d\n", arr[0]); // 10
printf("%d\n", *arr); // 10
printf("%d\n", *(arr + 1)); // 20
printf("%d\n", *p); // 10
p++;
printf("%d\n", *p); // 20
return 0;
}