[C] 문자열 상수와 문자열 변수의 차이

문자열 상수와 문자열 변수

문자열을 초기화하는 다음 두 가지 방법은 거의 비슷해 보이지만 근본적으로 완전히 다른 동작을 한다.

char *s1 = "abcdefg";
char s2[8] = "abcdefg";

첫번째 s1은 프로그램이 로딩될 때 정적영역에 "abcdefg"를 저장한 다음 이 시작 주소를 s1에 대입한다. 문자열 포인터는 s1에는 나중에 다른 주소의 값을 대입할 수 있다. 즉, s1자체는 변경이 가능한 포인터 변수이지만, 지금 s1이 가리키고 있는 문자열은 문자열 상수이므로 이 문자열을 변경할 수 없다. 반대로 s2는 힙 영역에 메모리를 할당한 후 "abcdefg"를 이곳에 저장했다. 따라서 s2에 담겨 있는 문자열은 변경이 가능하다. (각각의 바이트는 모두 개별 변수처럼 취급되므로)

간단한 예시를 보자. 다음 함수는 문자열을 모두 대문자로 만들어 주는 함수이다. (윈도우용 C컴파일러에 있는 함수임)

#include <ctype.h>
void strupr(char *origin) {
    char *temp = origin;
    while(*temp != '\0') {
        *temp = toupper(*temp);
    }
}

이 함수는 문자열 포인터(=문자열의 시작번지)를 인수로 받아, 각 문자를 대문자로 바꿔준다. toupper 함수는 표준 C 라이브러리에 포함되어 있는 함수이다. 만약 이 함수에 s1을 넘기면 프로그램이 다운된다. 문자열 상수를 변경하려는 시도를 했기 때문이다. 반대로 s2를 넘긴 경우에는 정상적으로 동작하는 것을 볼 수 있다. 다음은 전체 코드이다.

#include <stdio.h>
#include <ctype.h>
void strupr(char *origin);
int main(void) {
    char *s1 = "abcdefg";
    char s2[8] = "abcdefg";
    //printf("%s\n", strupr(s1)); // ==> 프로그램이 다운된다.
    printf("%s\n", strupr(s2)); // ==> 정상적으로 동작한다.
    return 0;
}
void strupr(char *origin) {
    char *temp = origin;
    while(*temp != '\0') {
        *temp = toupper(*temp);
    }
}

만약 문자열 상수로 만들어진 문자열을 사용하고자 한다면 다음과 같이 고친다.
char *s1 = "abcdefg";
char s2[8];
strcpy(s2,s1);

언뜻 생각하기에는 s2 = s1; 이라고 하면 안되나? 하는 생각이 들 수 있는데, 안된다. 비록 문자열 배열 변수의 변수명이 배열의 시작번지를 가리킨다고 해서 이것이 포인터라는 것은 아니다. 그것은 일종의 convension으로 배열의 변수명을 배열의 시작번지와 같이 다루는 것일 뿐이다. 즉, s2는 포인터 상수이고, 방금 예를 든 저 구문은 s2의 자리에 s1의 값 (정적영역내의 "abcdefg"가 자리잡은 메모리 번지)을 대입하고자 하는 시도이고, 이는 서로 타입이 맞지 않는 대입 구문이기 때문에 에러를 유발한다.

정리

  • 문자열 포인터로 문자열을 초기화하면 문자열 상수가 된다.
  • 배열로 선언한 문자열에 문자열을 집어넣을 때는 직접 대입이 아니라 strcpy를 쓰거나 한자 한자 루프를 돌면서 넣어야 한다.

Read more

워드프레스에서 고스트로 이전

워드프레스에서 고스트로 이전

이 글을 쓰면서도 믿기 힘든 사실인데, 블로그라는 걸 처음 시작한지가 20년이 되었습니다. 이글루스에서 처음 시작했다가, SK컴즈가 인수한다고 발표함과 동시에 워드프레스로 플랫폼을 옮겼죠. 워드프레스오 옮긴 이후에는 호스팅 환경을 이리 저리 옮기긴 했지만 거의 18년 가까이 워드프레스를 사용해온 것 같습니다. 그 동안 워드프레스는 블로깅 툴에서 명실상부한 범용CMS로 발전했습니다. 사실 웬만한 홈페이지들은 이제

By sooop
띄어쓰기에 대한 생각

띄어쓰기에 대한 생각

업무 메일을 쓸 때 가장 많이 쓰는 말 중에 하나가 메일 말미에 ‘업무에 참고 부탁 드립니다.‘인데요, 어느 날부터 아웃룩에서 이 ‘부탁 드립니다’가 틀렸다고 맞춤법 지적을 하기 시작했습니다. 맞는 말은 ‘부탁드립니다’라고 붙여 쓰는 거라고. 사실 아래아한글 시절부터 이전의 MS워드까지, 워드프로세서들의 한국어 맞춤법 검사 실력은 거의 있으나 마나 한

By sooop

구글 포토에서 아이클라우드로 탈출한 후기

한 때 구글 포토가 백업 용량을 무제한으로 제공해 주겠다고해서, 구글 포토를 사용해서 사진을 백업해왔습니다. 물론 이 이야기의 결말은 저나 이 글을 읽고 있는 여러분이나 모두 알고 있습니다. 사실 AI에게 학습 시킬 이미지 데이터를 모으기 위한 것일 뿐이라거나 하는 이야기는 그 당시에도 있었습니다만, 에이 그래도 구글인데 용량은 넉넉하게 주겠지…하는 순진한

By sooop

Julia의 함수 사용팁

연산자의 함수적 표기 Julia의 연산자는 기본적으로 함수이며, 함수 호출 표기와 같은 방식으로 호출하는 것이 가능합니다. 또한 그 자체로 함수이기 때문에 filter(), map() 과 같이 함수를 인자로 받는 함수에도 연산자를 그대로 적용하는 것이 가능합니다. 특히 + 연산자는 sum() 함수와 같이 여러 인자를 받아 인자들의 합을 구할 수 있습니다. 2 + 3 # = 5 +(2,

By sooop