문자열과 포인터

문자열 상수와 포인터

  • 문자열 상수 : 큰따옴표(“”) 안에 나열한 일련의 문자
  • 이 문자열 상수는 “상수” 이며 문자형의 배열이 아니다.
  • 따라서 포인터로 문자열 상수를 가리킬 경우, 포인터를 이용해 문자열의 내용을 수정할 수 없다.
1
2
3
4
5
6
7
// array_and_pointer.c
char *cp = "computer";
printf("cp        : %p\n", cp);
printf("*cp(char) : %c\n", *cp);
printf("*(cp+1)   : %c\n", *(cp+1));
printf("cp(str)   : %s\n", cp);
printf("*cp(str)  : %s\n", *cp);
1
2
3
4
5
6
# 출력
cp        : 0x10019897f
*cp(char) : c
*(cp+1)   : o
cp(str)   : computer
zsh: segmentation fault  ./array_and_pointer # 에러

즉, 포인터 변수에 문자열 상수가 저장되는 것이다.
따라서 포인터를 이용해 문자열의 내용을 수정할 수 없다.

1
2
3
4
// array_and_pointer.c
char *cp = "computer";
*(cp+2) = 'T';
printf("%s\n", cp);
1
zsh: segmentation fault  ./array_and_pointer
1
2
3
4
5
6
7
8
9
cp ---> |   c   | *cp
        |   o   | *(cp+1)
        |   m   | *(cp+2)
        |   p   | *(cp+3)
        |   u   | *(cp+4)
        |   t   | *(cp+5)
        |   e   | *(cp+6)
        |   r   | *(cp+7)
        |   \0  | *(cp+8)

문자형 배열과 포인터

  • 문자형 배열의 경우, 해당 배열의 이름은 배열의 시작 주소를 나타낸다.
  • 따라서 문자형 배열의 이름은 포인터로 사용할 수 있다.
  • 문자형 배열에 대한 포인터는 포인터 연산을 통해 배열의 각 요소에 접근할 수 있다.
  • 또한 포인터를 배열처럼 사용할 수도 있다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
char str[] = "computer";
char *cp = &str;

printf("cp      : %p\n", cp);
printf("&str    : %p\n", &str);
printf("--------------------\n");
printf("| No | *(cp+n) | *(str+n) |  cp[n]  |  str[n]  |\n");
printf("| %2d |    %c    |    %c     |   %c     |    %c     |\n", 0, *cp, *str, cp[0], str[0]);
printf("| %2d |    %c    |    %c     |   %c     |    %c     |\n", 1, *(cp + 1), *(str + 1), cp[1], str[1]);
printf("| %2d |    %c    |    %c     |   %c     |    %c     |\n", 2, *(cp + 2), *(str + 2), cp[2], str[2]);
printf("| %2d |    %c    |    %c     |   %c     |    %c     |\n", 3, *(cp + 3), *(str + 3), cp[3], str[3]);
printf("| %2d |    %c    |    %c     |   %c     |    %c     |\n", 4, *(cp + 4), *(str + 4), cp[4], str[4]);
printf("| %2d |    %c    |    %c     |   %c     |    %c     |\n", 5, *(cp + 5), *(str + 5), cp[5], str[5]);
printf("| %2d |    %c    |    %c     |   %c     |    %c     |\n", 6, *(cp + 6), *(str + 6), cp[6], str[6]);
printf("| %2d |    %c    |    %c     |   %c     |    %c     |\n", 7, *(cp + 7), *(str + 7), cp[7], str[7]);
printf("| %2d |    %2c    |    %2c     |   %2c     |    %2c     |\n", 8, *(cp + 8), *(str + 8), cp[8], str[8]);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 출력
cp      : 0x13fc12788
&str    : 0x13fc12788
--------------------
| No | *(cp+n) | *(str+n) |  cp[n]  |  str[n]  |
|  0 |    c    |    c     |   c     |    c     |
|  1 |    o    |    o     |   o     |    o     |
|  2 |    m    |    m     |   m     |    m     |
|  3 |    p    |    p     |   p     |    p     |
|  4 |    u    |    u     |   u     |    u     |
|  5 |    t    |    t     |   t     |    t     |
|  6 |    e    |    e     |   e     |    e     |
|  7 |    r    |    r     |   r     |    r     |
|  8 |         |          |         |          |


문자형 배열도 배열처럼 쓸 수도 있고, 포인터처럼 쓸 수도 있으며
이를 가리키는 포인터도 배열처럼 쓸 수도 있고, 포인터처럼 쓸 수도 있다.

Reference

C 프로그래밍 (김형근, 곽덕훈, 정재화 공저)
C 프로그래밍 강의 (방송통신대 - 이병래)

Comments