기본 콘텐츠로 건너뛰기

방송대 방통대 C프로그래밍 10강 - 배열과 포인터(3) - 요약 노트 시험족보 예상문제 - 올에이클래스

C프로그래밍 10강 - 배열과 포인터(3)

C프로그래밍 10강 - 배열과 포인터(3)

문자열과 1·2차원 배열을 포인터로 참조하는 방법을 익히고 배열식과 포인터식의 호환 관계를 이해한다. 포인터 배열의 효율적인 문자열 처리와 포인터를 다시 가리키는 이중 포인터의 선언·참조 구조도 함께 정리한다.

1. 문자열과 포인터

C의 문자열 상수는 큰따옴표 안에 나열한 일련의 문자이며 마지막에 널 문자 '\0'가 붙는다. char 포인터에 문자열 상수의 시작 주소를 저장하면 포인터 산술로 각 문자를 차례로 참조할 수 있다.

char *cp = "COMPUTER";

*(cp + 0)  /* 'C' */
*(cp + 1)  /* 'O' */
*(cp + 7)  /* 'R' */
*(cp + 8)  /* '\0' */

강의에서는 포인터 cp가 가리키는 대상이 문자열 상수이므로 *cp = 'C';처럼 포인터를 통해 문자열 내용을 수정할 수 없다고 설명한다. 읽기와 수정 가능 여부를 구분해야 한다.

int i = 0;
while (*(cp + i) != 0) {
    printf("%c", *(cp + i));
    i++;
}

널 문자를 만날 때까지 포인터식으로 문자를 출력하면 COMPUTER가 출력된다. 널 문자는 문자 값 0이므로 조건식에서 *(cp+i) != 0으로 문자열의 끝을 검사할 수 있다.

문자열 상수의 주소를 받은 포인터로 각 문자를 읽을 수는 있지만 그 포인터를 통해 문자열 상수의 내용을 수정해서는 안 된다.

2. 1차원 배열과 포인터

1차원 배열의 이름은 배열의 시작 주소이다. 포인터가 배열의 시작을 가리키면 배열명은 포인터처럼, 포인터는 배열처럼 사용할 수 있다.

char s[] = "SCIENCE";
char *cp = s;

s[2]       /* 'I' */
*(s + 2)   /* 'I' */
cp[2]      /* 'I' */
*(cp + 2)  /* 'I' */

위 네 식은 모두 같은 요소를 가리킨다. 문자열 SCIENCE의 일곱 문자 뒤에는 s[7] 위치에 널 문자가 저장된다.

포인터 이동과 식의 해석

static int a[] = {10, 20, 30, 40, 50};
int *pt = a;
int b = *pt + *(pt + 3);  /* 10 + 40 = 50 */
pt++;
int c = *pt + *(pt + 3);  /* 20 + 50 = 70 */
int d = *pt + 3;          /* 20 + 3 = 23 */

*(pt+3)은 포인터를 세 요소 이동한 곳의 값을 참조하지만, *pt+3은 현재 값에 정수 3을 더한다. 괄호 위치에 따라 결과가 50과 23처럼 달라지는 점이 중요하다.

3. 2차원 배열과 포인터

2차원 배열도 물리적으로는 행 우선 순서의 연속된 1차원 메모리 공간이다. int a[2][3]에서 a는 전체 배열의 시작 주소, a[0]a[1]은 각 행의 시작 주소이다.

int a[2][3] = {{1, 2, 3}, {4, 5, 6}};
int *pt = &a[0][0];  /* pt = a[0]도 가능 */

/* &a[i][j] == pt + i * 3 + j */
printf("%d", *(pt + 1 * 3 + 2));  /* 6 */

한 행의 열 수가 3이므로 i번째 행까지 이동하려면 i*3을 더하고, 그 행에서 j번째 열까지 j를 더한다. 따라서 요소 주소 공식은 &a[i][j] == pt + i*3 + j이다.

for (int i = 0; i < 2; i++) {
    for (int j = 0; j < 3; j++)
        printf("%d ", *(pt + i * 3 + j));
    printf("\n");
}

출력은 첫째 행 1 2 3, 둘째 행 4 5 6이다. 포인터를 하나씩 증가시키며 특정 종료값을 만날 때까지 2차원 배열 전체를 연속적으로 처리하는 방식도 사용할 수 있다.

4. 포인터와 배열의 관계

포인터와 배열은 요소를 참조할 때 호환적인 표현을 사용할 수 있다. 배열 A는 *(A+i)로, 포인터 p는 p[i]로 참조할 수 있다.

항목배열포인터
요소 참조A[i], *(A+i)p[i], *(p+i)
가리키는 위치 변경배열명은 상수처럼 취급되어 변경 불가p++ 등으로 변경 가능
자료 영역기억공간을 고정적으로 확보필요할 때 유동적으로 확보 가능
int A[5] = {1, 2, 3, 4, 5};
int *p = A;

p++;  /* 가능: 이제 2를 가리킴 */
/* A++;  오류: 배열명 자체는 변경할 수 없음 */

표현은 호환되지만 배열명과 포인터 변수가 완전히 같은 것은 아니다. 포인터는 가리키는 곳을 변경할 수 있지만 배열명은 시작 위치를 나타내는 상수처럼 취급된다. 강의에서는 배열은 자료 영역을 고정적으로 확보하고, 포인터는 필요한 때 자료용 공간을 유동적으로 확보하여 자료 개수가 가변적일 때 효과적이라고 비교한다.

배열식과 포인터식이 같은 요소를 참조한다는 사실과 배열명 자체를 증가시킬 수 없다는 사실을 함께 기억해야 한다.

5. 포인터 배열의 개념

포인터 배열은 포인터를 요소로 저장하는 배열이다. 여러 포인터를 하나의 배열로 관리할 때 사용하며, 강의에서는 주로 문자열 배열 처리에 활용한다고 설명한다.

char *name1, *name2, *name3;
char *name[3];  /* char 포인터 3개를 저장하는 배열 */

char *name[3]에서 name은 배열이고, name[0], name[1], name[2]는 각각 char형 자료를 가리키는 포인터이다. 한 행의 문자열 길이가 일정하지 않을 때 고정된 열 수를 갖는 2차원 문자 배열보다 효율적으로 활용할 수 있다.

6. 포인터 배열을 이용한 문자열 처리

2차원 문자 배열

char str[3][10] = {
    "KNOU", "Computer", "123456789"
};

모든 행에 10칸을 확보하므로 첫 문자열 KNOU는 널 문자를 포함해 5칸만 필요하지만 10칸을 사용한다. 행마다 길이가 달라도 열 크기는 동일하다.

문자열 포인터 배열

char *str[3] = {
    "KNOU", "Computer", "123456789"
};

for (int i = 0; i < 3; i++) {
    for (int j = 0; str[i][j]; j++)
        printf("%c", str[i][j]);
    printf("\n");
}

포인터 배열의 각 요소는 길이가 서로 다른 문자열의 시작 주소를 저장한다. str[i][j]가 널 문자가 아닌 동안 각 문자를 출력하면 세 문자열이 한 줄씩 출력된다.

문자열 길이가 일정하지 않으면 포인터 배열이 고정 열 크기의 2차원 배열보다 불필요한 공간을 줄이는 데 유리하다.

7. 이중 포인터

이중 포인터(pointer to pointer)는 포인터를 가리키는 포인터이다. 이중 포인터가 직접 가리키는 곳에는 실제 자료가 아니라 다른 포인터, 즉 주소 값이 들어 있고 그 포인터가 다시 실제 자료를 가리킨다.

자료형 **포인터변수명;

int **p;
표현의미
p이중 포인터 자체
*pp가 가리키는 곳의 int형 포인터
**p그 int형 포인터가 가리키는 실제 int 자료
char a = 'A';
char *p = &a;
char **pp = &p;

printf("%c\n", **pp);  /* A */

p에는 a의 주소가, pp에는 p의 주소가 저장된다. *pp는 p이고, 한 번 더 참조한 **pp는 a의 값 'A'이다. 주소 연결을 pp → p → a 순서로 추적하면 이해하기 쉽다.

핵심 개념 정리

  • char 포인터는 문자열 상수의 시작 주소를 저장하고 포인터 산술로 각 문자를 읽을 수 있다.
  • 문자열 상수는 그 주소를 받은 포인터를 통해 수정할 수 없다.
  • 1차원 배열에서 s[i], *(s+i), cp[i], *(cp+i)는 같은 요소를 참조할 수 있다.
  • 2차원 배열은 메모리에 연속 배치되며 열 수가 3이면 &a[i][j] == pt+i*3+j이다.
  • 배열명은 위치를 변경할 수 없지만 포인터 변수는 증가·감소로 참조 위치를 바꿀 수 있다.
  • 포인터 배열은 포인터를 저장하며 길이가 서로 다른 문자열 처리에 효율적이다.
  • 이중 포인터는 포인터를 가리키고, 두 번 참조하면 최종 자료에 접근한다.

최종 정리: 배열과 포인터는 요소 참조 표현을 서로 바꿔 쓸 수 있지만 저장공간의 성격과 위치 변경 가능 여부는 다르다. 포인터 배열은 여러 주소를 한 배열로 관리하고, 이중 포인터는 주소를 저장한 포인터의 주소를 다시 연결하는 구조이다.

예상문제 20선

1. char *cp="COMPUTER";에서 cp가 저장하는 것은?

정답입니다.

오답입니다. 답안을 다시 선택해 보세요.

정답 및 해설 보기

정답: ①
char 포인터 cp에는 문자열 상수 COMPUTER가 시작하는 주소가 저장된다.

2. 위 cp에 대해 *(cp+2)의 값은?

정답입니다.

오답입니다. 답안을 다시 선택해 보세요.

정답 및 해설 보기

정답: ②
첨자는 0부터 시작하므로 세 번째 문자 M을 참조한다.

3. 문자열 상수의 주소를 받은 cp에 대해 부적절한 문장은?

정답입니다.

오답입니다. 답안을 다시 선택해 보세요.

정답 및 해설 보기

정답: ③
강의에서는 문자열 상수를 포인터를 통해 수정하는 문장을 부적절하다고 설명한다.

4. C 문자열의 끝을 판별하는 값은?

정답입니다.

오답입니다. 답안을 다시 선택해 보세요.

정답 및 해설 보기

정답: ④
문자열의 마지막에는 값 0인 널 문자가 저장된다.

5. char s[]="SCIENCE"; char *cp=s;에서 같은 요소를 나타내는 묶음은?

정답입니다.

오답입니다. 답안을 다시 선택해 보세요.

정답 및 해설 보기

정답: ①
배열명과 배열을 가리키는 포인터는 첨자식과 포인터식을 호환해 사용할 수 있다.

6. pt가 값 20을 가리킬 때 *pt+3의 결과는?

정답입니다.

오답입니다. 답안을 다시 선택해 보세요.

정답 및 해설 보기

정답: ②
*pt+3은 현재 참조값 20에 정수 3을 더한다.

7. int a[2][3]에서 a[1]이 나타내는 것은?

정답입니다.

오답입니다. 답안을 다시 선택해 보세요.

정답 및 해설 보기

정답: ③
a[0]과 a[1]은 각각 첫째 행과 둘째 행의 시작 주소이다.

8. 열 수가 3이고 pt가 a[0][0]을 가리킬 때 a[i][j]의 주소식은?

정답입니다.

오답입니다. 답안을 다시 선택해 보세요.

정답 및 해설 보기

정답: ④
i개 행은 각 3요소이므로 i×3만큼 이동한 뒤 열 첨자 j를 더한다.

9. 배열명과 포인터 변수의 차이로 옳은 것은?

정답입니다.

오답입니다. 답안을 다시 선택해 보세요.

정답 및 해설 보기

정답: ①
배열명은 시작 위치를 나타내는 상수처럼 취급되지만 포인터 변수의 값은 변경할 수 있다.

10. 배열의 기억공간 확보 특성은?

정답입니다.

오답입니다. 답안을 다시 선택해 보세요.

정답 및 해설 보기

정답: ②
강의는 배열이 자료 영역의 기억공간을 고정적으로 확보한다고 비교한다.

11. 자료 개수가 가변적일 때 더 적합하다고 설명한 것은?

정답입니다.

오답입니다. 답안을 다시 선택해 보세요.

정답 및 해설 보기

정답: ③
포인터는 필요한 때 자료용 공간을 확보할 수 있어 자료 개수가 가변적일 때 효과적이다.

12. 포인터 배열의 정의는?

정답입니다.

오답입니다. 답안을 다시 선택해 보세요.

정답 및 해설 보기

정답: ④
포인터 배열의 각 요소는 주소 값을 저장하는 포인터이다.

13. char 포인터 3개를 저장하는 배열 선언은?

정답입니다.

오답입니다. 답안을 다시 선택해 보세요.

정답 및 해설 보기

정답: ①
name은 크기 3의 배열이고 각 요소의 형은 char 포인터이다.

14. 포인터 배열이 2차원 문자 배열보다 효율적일 수 있는 경우는?

정답입니다.

오답입니다. 답안을 다시 선택해 보세요.

정답 및 해설 보기

정답: ②
고정 열 크기의 남는 공간을 줄이고 각기 다른 길이의 문자열 주소를 저장할 수 있다.

15. char str[3][10]에서 "KNOU" 행에 확보되는 칸 수는?

정답입니다.

오답입니다. 답안을 다시 선택해 보세요.

정답 및 해설 보기

정답: ③
각 행의 열 크기가 10으로 고정되어 있어 실제 문자열이 짧아도 10칸을 확보한다.

16. 문자열 출력 반복문에서 str[i][j]가 거짓이 되는 때는?

정답입니다.

오답입니다. 답안을 다시 선택해 보세요.

정답 및 해설 보기

정답: ④
널 문자의 값은 0이므로 조건식에서 거짓이 되어 한 문자열의 반복이 끝난다.

17. 이중 포인터란?

정답입니다.

오답입니다. 답안을 다시 선택해 보세요.

정답 및 해설 보기

정답: ①
이중 포인터가 가리키는 곳에는 실제 값이 아니라 다른 포인터가 저장되어 있다.

18. int형 이중 포인터의 선언은?

정답입니다.

오답입니다. 답안을 다시 선택해 보세요.

정답 및 해설 보기

정답: ②
자료형 뒤에 별표 두 개를 붙여 이중 포인터로 선언한다.

19. int형 이중 포인터 p에서 *p가 나타내는 것은?

정답입니다.

오답입니다. 답안을 다시 선택해 보세요.

정답 및 해설 보기

정답: ③
p를 한 번 참조하면 중간 포인터가 나오고 두 번 참조해야 최종 int 자료가 나온다.

20. char a='A', *p=&a, **pp=&p;에서 **pp는?

정답입니다.

오답입니다. 답안을 다시 선택해 보세요.

정답 및 해설 보기

정답: ④
pp를 한 번 참조하면 p, 다시 참조하면 p가 가리키는 a의 값 A가 나온다.

댓글