C 언어에서 string이 없는 이유 – 문자열과 포인터의 관계
C 언어에서 문자열과 포인터 이해하기
C 언어에서는 문자열을 다룰 때 string이라는 자료형을 사용하는 것처럼 보이지만, 사실 C에는 string이라는 자료형이 존재하지 않는다. 대신, 문자열은 문자의 배열로 표현되며, 이 배열을 가리키는 포인터를 사용해 문자열을 저장하고 접근할 수 있다. 이번 글에서는 문자열이 메모리에 어떻게 저장되는지, 그리고 이를 다루는 포인터의 개념을 쉽게 이해할 수 있도록 기록해보고자 한다(:
문자열과 포인터의 관계
예제 코드를 살펴보자.
#include <stdio.h>
int main(void)
{
char *s = "EMMA";
printf("%s\n", s);
}
이 코드에서 s는 문자열의 첫 번째 문자를 가리키는 포인터다. 즉, s는 "EMMA"라는 문자열이 저장된 메모리 주소를 저장하는 포인터 변수다. 하지만 여기서 중요한 점은 s 자체는 문자열이 아니라, 문자열이 저장된 메모리의 시작 주소를 가리키는 포인터라는 것이다.
문자열의 메모리 구조
문자열 "EMMA"는 메모리에 다음과 같이 저장될 수 있다.
메모리 주소 값
0x1000 | 'E' |
0x1001 | 'M' |
0x1002 | 'M' |
0x1003 | 'A' |
0x1004 | '\0' |
즉, s는 0x1000을 가리키고 있으며, 이를 통해 문자열을 출력할 수 있다. printf("%s\n", s);는 s가 가리키는 주소부터 시작해서 \0(널 문자)을 만날 때까지 문자를 출력한다.
만약 s를 통해 두 번째 문자를 출력하고 싶다면?
printf("%c\n", s[1]);
이렇게 하면 s[1]이 0x1001에 저장된 'M'을 가리키므로 'M'이 출력된다.
string 자료형이란?
CS50 라이브러리를 보면 string 자료형이 아래와 같이 정의되어 있다.
typedef char *string;
여기서:
- typedef : 새로운 자료형을 정의하는 키워드
- char * : 문자형 데이터를 가리키는 포인터
- string : 우리가 새롭게 정의한 자료형 이름
즉, string은 사실 char *의 별명(alias)일 뿐이며, 실제로는 문자열을 가리키는 포인터다. 그래서 아래 두 코드는 완전히 동일하게 동작한다.
string을 사용한 코드
#include <cs50.h>
#include <stdio.h>
int main(void)
{
string s = "EMMA";
printf("%s\n", s);
}
char *을 사용한 코드
#include <stdio.h>
int main(void)
{
char *s = "EMMA";
printf("%s\n", s);
}
즉, CS50 라이브러리에서는 string을 정의해 사용하지만, 사실 char *을 직접 사용하는 것이 C 언어의 원래 방식이다.
포인터와 변수명
처음 포인터를 배울 때, p라는 변수명을 자주 보게 된다. 하지만 p는 C에서 공식적으로 정해진 것이 아니라, 단순히 많이 쓰이는 변수명일 뿐이다. 즉, 포인터 변수명을 p, ptr, pointerToX 등으로 자유롭게 정할 수 있다.
예를 들어, 아래 코드는 모두 같은 의미다.
int x = 10;
int *p = &x; // 포인터 변수명 p 사용
int *ptr = &x; // ptr 사용
int *pointerToX = &x; // 조금 더 설명적인 변수명 사용
위 코드에서 중요한 점은 변수명(p, ptr, pointerToX)이 아니라, * 연산자를 통해 포인터를 선언하는 것이다.
s가 첫 번째 문자만 가리키는 이유
문자열에서 s가 첫 번째 문자 'E'를 가리키는 이유는 C에서 문자열이 배열로 저장되기 때문이다.
char *s = "EMMA";
이렇게 선언하면 "EMMA"라는 문자열이 메모리에 저장되고, s는 그 첫 번째 문자가 있는 메모리 주소를 저장하는 포인터가 된다. s는 s[0]의 주소(즉, 'E'의 주소)를 가리킨다.
하지만 s 자체가 단일 문자를 저장하는 것이 아니라, 문자열의 첫 번째 문자가 있는 메모리 주소를 저장하고 있기 때문에 포인터 연산을 사용하면 다음 문자로 이동할 수 있다.
예를 들어, s + 1을 출력하면?
printf("%s\n", s + 1);
출력 결과:
MMA
이는 s + 1이 'M'이 있는 메모리 주소를 가리키게 되기 때문이다.
string을 사용하는 이유
그렇다면 CS50에서 string을 따로 정의해서 사용하는 이유는 무엇일까?
- 코드 가독성 증가
- char *보다는 string이 직관적으로 보이므로 초보자가 이해하기 쉬움.
- 일관성 유지
- CS50 라이브러리 내에서 문자열을 다룰 때 일관된 표현을 사용하기 위함.
- 초보자 친화적
- string이라는 키워드가 파이썬 등 다른 언어의 개념과 비슷하여, 입문자들이 쉽게 적응할 수 있음.
하지만 결국 string은 char *의 별명이므로, C의 원래 방식대로 코드를 작성할 때는 char *을 사용하는 것이 일반적이다.
+정리
- C 언어에서 문자열은 문자 배열로 저장되며, 이를 가리키는 포인터를 사용해 관리한다.
- char *s = "EMMA";에서 s는 첫 번째 문자 'E'의 주소를 가리킨다.
- string은 사실 char *의 별명일 뿐이며, C 언어 자체에는 존재하지 않는 자료형이다.
- 포인터 변수명(p, ptr, s 등)은 자유롭게 정할 수 있으며, 중요한 것은 *를 사용해 포인터임을 명시하는 것이다.
이제 C에서 문자열을 다룰 때, 포인터 개념을 이해하고 활용할 수 있겠지?🥰
'IT' 카테고리의 다른 글
C 언어 동적 메모리 할당 쉽게 이해하기 | malloc, free, valgrind 활용 (0) | 2025.03.30 |
---|---|
C 언어에서 문자열 복사하는 방법: malloc과 for문을 활용한 정확한 복사 (0) | 2025.03.30 |
인터넷 속도 계산법 : 1Gbps, 100Mbps 다운로드 속도 비교 (0) | 2025.03.28 |
C 프로그래밍에서 16진수와 메모리 주소 이해하기: 포인터와 역참조까지 (0) | 2025.03.27 |
병합 정렬(Merge Sort) : 효율적인 정렬 알고리즘 배우기 (0) | 2025.03.25 |
댓글
이 글 공유하기
다른 글
-
C 언어 동적 메모리 할당 쉽게 이해하기 | malloc, free, valgrind 활용
C 언어 동적 메모리 할당 쉽게 이해하기 | malloc, free, valgrind 활용
2025.03.30 -
C 언어에서 문자열 복사하는 방법: malloc과 for문을 활용한 정확한 복사
C 언어에서 문자열 복사하는 방법: malloc과 for문을 활용한 정확한 복사
2025.03.30 -
인터넷 속도 계산법 : 1Gbps, 100Mbps 다운로드 속도 비교
인터넷 속도 계산법 : 1Gbps, 100Mbps 다운로드 속도 비교
2025.03.28 -
C 프로그래밍에서 16진수와 메모리 주소 이해하기: 포인터와 역참조까지
C 프로그래밍에서 16진수와 메모리 주소 이해하기: 포인터와 역참조까지
2025.03.27