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

[C 언어] 문자열 상수 구현 방법

by khsnote22 2022. 12. 9.

문자열은 크기가 일정하지 않습니다. 따라서 컴파일러는 문자열 상수를 독특한 방법으로 처리합니다. 컴파일 과정에서 문자열을 char 배열 형태로 따로 보관하고 문자열 상수가 있던 곳에는 배열의 위치 값을 사용합니다. 예를 들어 문자열 "apple"은 문자 'a'가 저장된 메모리의 주소 값으로 바뀝니다. 

 

// 문자열 상수가 주소란 증거
#include <stdio.h>

int main(void)
{
	printf("apple이 저장된 시작 주소 값 : %p\n", "apple"); // 주소 값 출력
    printf("두 번째 문자의 주소 값 : %p\n", "apple" +1); // 주소 값 출력
    printf("첫 번째 문자 : %c\n", *"apple");
    printf("두 번째 문자 : %c\n", *("apple"+1));
    printf("배열로 표현한 세 번째 문자 : %c\n", "apple"[2]);
    
    return 0;
}

5행은 문자열이 저장된 곳의 위치 값을 출력합니다. 문자열 "apple"은 배열 형태로 따로 저장되고 printf 함수의 인수로 그 첫 번째 문자의 주소가 사용됩니다. printf 함수에서 %p로 출력하면 그 값을 16진수로 확인할 수 있습니다. p는 주로 포인터를 출력할 때 사용하는 변환 문자며 포인터 값을 16진수 대문자로 출력합니다. 결국 문자열은 컴파일 과정에서 char 변수의 주소로 바뀌므로 직접 포인터 연산을 수행할 수 있습니다. 6행처럼 정수를 더하면 다음 문자인 주소를 구할 수 있고 7행과 같이 간접 참조 연산을 수행하면 첫 번째 문자가 됩니다. 9행과 같이 배열명처럼 사용하는 것도 가능합니다. 단, 반드시 명심해야 할 것이 있습니다.

 

주의

주소로 접근하여 문자열을 바꿔서는 안 됩니다. 즉 *"apple" = 't';와 같이 첫 번째 문자가 저장된 공간에 다른 문자를 대입하여 그 값을 바꾸려는 시도는 위험합니다. 연산 자체는 문제가 없으므로 정상적으로 컴파일되지만 실행할 때 운영체제에 의해서 강제 종료될 가능성이 있습니다. 운영체제는 문자열 상수를 읽기 전용 메모리 영역에 저장합니다. 따라서 그 값을 바꾸는 명령의 실행을 제한합니다. 운영체제에 따라 다를 수 있으나 호환성을 고려한다면 시도하지 마십시오.

문자열을 주소로 바꾸면 포인터 연산을 통해 문자열의 시작 위치부터 길이 제한 없이 사용할 수 있습니다. 이 경우 문자열의 끝을 알아야 하므로 문자열의 끝을 표시하기 위해 널 문자를 사용합니다. 따라서 컴파일러는 문자열 상수를 따로 저장할 때 마지막에 항상 널 문자를 붙여줍니다.