본문 바로가기
프로그래밍/C언어

C언어 공부하기 - 문자열과 배열

by 헬맷쓰다 2020. 10. 28.
반응형

이번 시간에는 많이 쓰이는 문자열(Character Strings), 문자배열에 대해서 알아보겠습니다.

생각보다 간단한데요, 문자열이란 이름, 단어, 문장 등 문자들로 이루어진 배열입니다. 그리고 끝은 항상 널(Null)문자 즉 '\0'로 끝이 납니다. 널문자는 문자 '0'이 아니라 값이 0이므로 '\'뒤에 '0'을 붙여준 겁니다. 만약에 "Hello!"라는 문자열을 사용한다고 합시다. 그러면 아래와 같이 두가지 방법으로 정의를 할 수 있습니다.

char  hello_array[] = "Hello!";
char *hello_pointer = "Hello!";

 

첫번째 정의는 크기를 지정하지 않은 문자형 배열에 "Hello!"를 지정한 겁니다.

두번째 정의는 hello_pointer라는 문자형 포인터가 "Hello!"를 가리키도록 지정한 겁니다. 정확히 말하면, 'H'가 저장된 주소를 가리킵니다. 감이 안오신다면 그림으로 표현하겠습니다.

 

 

이 둘의 정의는 매우 비슷한 것 같지만 아주 중요한 차이점이 있습니다. hello_array는 문자형 배열이니까 메모리의 일정한 장소에 할당되어 있고, 배열의 각 요소를 변경할 수 있습니다. 

그런데, hello_pointer는 문자형 포인터가 "Hello!"라는 문자열을 가리키고 있기 때문에 다른 위치로 변경이 가능하지만 배열처럼 내용을 변경할 수가 없습니다. 포인터를 사용할 때, 내용을 변경할 수 없으므로 문자열 상수를 다룬다고도 이야기 합니다. 상수는 변경할 수 없다는 것 기억하시죠?

자 그럼 몇 가지 예제를 통해 문자열에 대해 더 알아 보도록 하죠.

위 예제에서 문자열의 길이는 어떻게 될까요?  문자열의 길이는 6자입니다. 널문자 '\0'바로 앞의 문자까지의 길이입니다. 라이브러리 함수로 strlen이라는 함수가 있습니다. string관련 라이브러리 함수는 대부분 string.h에 있기 때문에 헤더파일로 포함시켜 줘야 에러없이 컴파일이 됩니다.

#include <stdio.h>
#include <string.h>

void main()
{
    char hello_array[] = "Hello!";
    char *hello_pointer = "Hello!";

    printf ("arr_length = %d\n", strlen(hello_array));
    printf ("ptr_length = %d\n", strlen(hello_pointer));
}

PS C:\CS> .\string1.exe
arr_length = 6
ptr_length = 6

 

만약에 문자열 중간에 널(NULL)문자가 있으면 어떻게 인식을 할까요? 다음 코드를 한번 보시죠.

 char hello_array[] = "Hello!\0World!";
 char *hello_pointer = "Hello!\0World!";

 

"Hello!" 바로 뒤에 널문자가 있고 그 뒤에 다른 문자들이 있네요. C언어에서 문자열은 널문자로 끝난다고 했기 때문에 문자열의 맨 앞에서 널문자를 만나면 문자열의 끝으로 인식합니다. 따라서 널문자 뒤의 문자들은 무시됩니다. 문자열을 다룰땐 정말 주의를 해야 합니다.

위에서 문자열의 길이를 알아내는 함수인 strlen을 직접 정의해 볼께요.

int my_strlen(char string[])
{
    int i=0;
    while (string[i] != 0)
        i++;
    return i;
}

int my_strlen1(char *string)
{
    int i=0;
    while (*string++ != 0)
        i++;
    return i;
}

 

함수를 두개 작성했는데요. 첫번째 my_strlen은 크기 없는 배열을 함수의 인자로 사용했고, 두번째 my_strlen1은 문자형 포인터를 사용했습니다. 어떤 것을 사용해도 동일하게 작동을 합니다. 사실 배열의 이름이 배열의 첫번째 요소이고 포인터도 배열의 첫번째 요소를 가리킨다고 했으니 서로 혼용해서 사용해도 별 문제는 없습니다.

즉, my_strlen함수의 내용과 my_strlen1함수의 내용을 서로 바꿔도 문제없이 컴파일 되고 실행도 잘 됩니다. 

참! 문자형 배열은 내용을 변경할 수 있고, 문자열 포인터를 변경할 수 없다고 하는데 변경을 시도하면 어떻게 될까요? 다음과 같은 코드가 있다고 합시다.

char  hello_array[] = "Hello!";
char *hello_pointer = "Hello!";

hello_array[0] = 'W';
hello_pointer[0] = 'X';

 

이게 어떻게 될까요? 위코드의 마지막 줄을 제외하고 컴파일 실행에는 문제없었습니다. 마지막 줄을 추가한 후에 윈도우 환경 gcc로 컴파일 했을 때 오류는 없었습니다만...프로그램은 중간에 죽어버렸습니다.

문자열과 배열은 이 정도로 마치고 다음에는 문자열 관련된 라이브러리 함수들을 직접 구현해 보는 시간을 갖겠습니다. 안녕~

 

반응형

댓글