C 배열·문자열·포인터
쉽게 말하면
배열은 같은 종류의 값을 줄지어 담는 상자 묶음이고, 첫 칸 번호는 0이에요. 포인터는 값이 아니라 '값이 있는 주소'를 담는 변수예요. &x는 x의 주소, *p는 p가 가리키는 곳의 값이에요. 배열 이름은 첫 칸의 주소라서 *(a + 2)는 a[2]와 같아요. 문자열은 글자 배열이고 끝에 보이지 않는 '\0'(널 문자)이 하나 더 붙어요.
시험용 정의
배열은 같은 자료형 값을 연속된 메모리에 저장하며 인덱스는 0부터 시작한다. 배열 이름은 첫 요소의 주소이므로 a[i]와 *(a + i)는 같다. 포인터는 주소를 저장하는 변수로, &변수는 주소, *포인터는 가리키는 곳의 값(간접 참조)이다. 포인터에 1을 더하면 자료형 크기만큼 다음 요소로 이동한다(int면 4바이트). 포인터의 포인터(**pp)는 포인터의 주소를 담는다. 문자열은 char 배열이며 끝에 널 문자 '\0'이 붙어 char s[] = "KOREA"의 sizeof는 6, strlen은 5다. 2차원 배열 b[i][j]는 *(*(b + i) + j)와 같다. 구조체는 서로 다른 자료형을 묶은 사용자 정의형으로, 변수는 .(점), 포인터는 ->로 멤버에 접근한다.
비유로 이해하기
아파트로 비유하면 배열은 같은 평형 집이 0호부터 줄지은 동, 포인터는 '302호'라고 적힌 쪽지다. 쪽지를 따라가면(*) 집 안의 물건(값)을 볼 수 있고, 쪽지 번호에 1을 더하면 옆집이다.
자세히
먼저 알아 둘 말
| 말 | 뜻 |
|---|---|
| 인덱스 | 배열 칸 번호. 0부터 시작 |
| 주소 | 메모리 위치를 가리키는 번호 |
| & (주소 연산자) | 변수의 주소를 구한다 |
| * (간접 참조 연산자) | 포인터가 가리키는 곳의 값 |
| 널 문자 '\0' | 문자열 끝을 알리는 값 0 |
| 구조체 | 여러 자료형을 하나로 묶은 형 (struct) |
예제 1: 배열과 포인터
int a[5] = {10, 20, 30, 40, 50};
int *p = a;
printf("%d %d %d\n", *p, *(p + 2), *p + 2); // 10 30 12
p++; // 이제 a[1]을 가리킴
printf("%d %d\n", *p, p[2]); // 20 40
int x = 10, *px = &x, **ppx = &px;
*px = 20;
**ppx += 5;
printf("%d\n", x); // 25예제 2: 문자열
char s[] = "KOREA";
printf("%d %d %c %s\n", strlen(s), sizeof(s), s[2], s + 3);
// 5 6 R EA
char w[] = "ABCDE";
for (int i = 0; i < 2; i++) { // 앞뒤 바꾸기
char tmp = w[i]; w[i] = w[4 - i]; w[4 - i] = tmp;
}
printf("%s\n", w); // EDCBA- s + 3은 'E'부터 시작하는 문자열이라 %s로 찍으면 EA
- sizeof는 '\0'까지 6, strlen은 글자 수 5
예제 3: 2차원 배열과 구조체
int b[2][3] = {{1, 2, 3}, {4, 5, 6}};
printf("%d %d\n", b[1][0], *(*(b + 1) + 2)); // 4 6
struct st { char name[10]; int age; };
struct st t = {"kim", 20};
struct st *pt = &t;
pt->age += 1;
printf("%s %d\n", pt->name, t.age); // kim 21기출에서 더 나온 것
| 말 | 뜻 |
|---|---|
| strcmp(s1, s2) | 두 문자열을 비교한다. 같으면 0. 연결하는 함수는 strcat |
| strcat(s1, s2) | s1 뒤에 s2를 이어 붙인다 |
| 문자열 함수 (string.h) | strlen 길이, strcpy 복사, strcat 이어 붙이기, strcmp 비교 (같으면 0) |
시험에 이렇게 나와요
- 배열 값 구하기 → 초기화하지 않은 원소는 0
- 포인터 주소 계산 → 주소 + n은 n × (자료형 크기)만큼 이동
- 문자열 함수 → strlen 길이, strcpy 복사, strcat 연결, strcmp 비교
확인 문제
Q1. int a[5] = {10, 20, 30, 40, 50}; int *p = a; 일 때 *(p + 2)의 값은?
- 20
- 12
- 30
- 주소값
정답 보기
3번 30
p는 a[0]을 가리킨다. p + 2는 두 칸 뒤 a[2]의 주소이고, *를 붙이면 그 값 30. 반면 *p + 2는 10 + 2 = 12다. 괄호 위치에 주의.
Q2. int a[] = {1, 2, 3, 4}; int *p = a + 3; printf("%d", *p - *(p - 2));의 출력은?
- 1
- 2
- 3
- 4
정답 보기
2번 2
*p = a[3] = 4, *(p − 2) = a[1] = 2. 4 − 2 = 2.
Q3. char s[] = "HELLO";에서 sizeof(s)의 값은?
- 4
- 5
- 6
- 8
정답 보기
3번 6
글자 5개 + 널 문자 1개 = 6.
Q4. int a[5] = {10, 20, 30, 40, 50}; int s = 0; for (int i = 0; i < 5; i += 2) s += a[i]; 실행 후 s는?
- 50
- 60
- 90
- 150
정답 보기
3번 90
a[0] + a[2] + a[4] = 10 + 30 + 50 = 90.
Q5. 구조체 포인터 pt로 멤버 age에 접근하는 올바른 표현은?
- pt.age
- pt->age
- *pt.age
- &pt.age
정답 보기
2번 pt->age
포인터는 ->, (*pt).age도 같다. *pt.age는 우선순위 때문에 다른 뜻이다.
헷갈리기 쉬운 O·X
C에서 배열의 첫 번째 요소 인덱스는 1이다.
정답 보기
X 0부터 시작한다.
배열 이름 a는 a[0]의 주소와 같다.
정답 보기
O
int형 포인터 p에 1을 더하면 주소가 1바이트 늘어난다.
정답 보기
X int 크기(보통 4바이트)만큼 다음 요소로 이동한다.