C 언어에서 문자열 복사하는 방법: malloc과 for문을 활용한 정확한 복사
C 언어에서 문자열 복사하는 방법: malloc과 for문 사용하기
문자열 복사, 단순히 복사만 하면 되지 않나?
C 언어에서 문자열을 복사한다고 할 때, 단순히 문자열을 다른 변수에 대입하는 방식은 예기치 않은 결과를 초래할 수 있다. 이를 잘 이해하려면 먼저 C 언어에서 문자열이 어떻게 저장되는지를 알아야 한다. C 언어에서는 문자열이 메모리 주소에 저장되며, 각 문자열은 널 종료 문자(\0)로 끝난다. 이 때문에 단순히 문자열을 대입하면, 주소만 복사되고 실제 문자열의 내용은 복사되지 않는다.
예시 코드
#include <cs50.h>
#include <ctype.h>
#include <stdio.h>
int main(void)
{
string s = get_string("s: ");
string t = s;
t[0] = toupper(t[0]);
printf("s: %s\n", s);
printf("t: %s\n", t);
}
이 코드를 실행하면, 예를 들어 "emma"라는 문자열을 입력했을 때 s와 t 모두 "Emma"가 출력된다. 왜 이렇게 되는지 알아보자.
문제의 원인: 주소를 복사한 것
이 코드에서 string t = s;는 s의 주소를 t에 대입하는 것과 같다. s와 t는 같은 메모리 주소를 가리키고 있으며, t[0]을 수정하면 s[0]도 수정되게 된다. 그래서 t를 수정해도 s가 함께 변하는 결과가 발생한다.
그렇다면 문자열을 진짜로 복사하고 싶다면 어떻게 해야 할까?
malloc을 이용한 문자열 복사
메모리 상에서 문자열을 진짜 복사하려면, malloc을 이용해 새로운 메모리 공간을 할당하고 그 공간에 문자열을 복사해야 한다. 이 방법을 사용하면, s와 t는 각기 다른 메모리 공간을 가지게 되어 서로 독립적으로 동작한다.
수정된 코드
#include <cs50.h>
#include <ctype.h>
#include <stdio.h>
#include <string.h>
int main(void)
{
char *s = get_string("s: "); // 사용자로부터 문자열 입력받기
char *t = malloc(strlen(s) + 1); // 문자열의 길이만큼 메모리 할당, 널 종료 문자 공간 추가
// 문자열을 t에 복사
for (int i = 0, n = strlen(s); i < n + 1; i++) // 널 종료 문자까지 포함
{
t[i] = s[i]; // s에서 t로 문자 하나하나 복사
}
// 첫 번째 문자를 대문자로 변경
t[0] = toupper(t[0]); // 첫 번째 문자를 대문자로 바꾼다
// 출력
printf("s: %s\n", s); // s: 원본 문자열
printf("t: %s\n", t); // t: 첫 문자가 대문자인 문자열
}
malloc(strlen(s) + 1)에서 +1의 의미
위 코드에서 중요한 부분은 malloc(strlen(s) + 1);이다. 여기서 +1을 하는 이유는 널 종료 문자(\0)를 포함시키기 위해서다. C 언어에서 문자열은 \0으로 끝나므로, 문자열 길이만큼 메모리를 할당하고 그 끝에 \0이 저장될 공간도 추가로 확보해야 한다.
예를 들어, s = "emma"라면 실제로 메모리에서 이 문자열은 아래와 같이 저장된다:
- 'e', 'm', 'm', 'a', '\0' 이렇게 5개의 문자가 필요하다.
따라서 malloc(strlen(s) + 1)은 s의 길이(4)에 널 종료 문자 공간을 포함하여 5만큼 메모리를 할당하는 것이다.
문자열 복사: for문 이해하기
for문을 사용하여 s의 문자를 하나씩 t로 복사한다. 이 부분을 더 자세히 살펴보자.
for (int i = 0, n = strlen(s); i < n + 1; i++)
{
t[i] = s[i];
}
- int i = 0, n = strlen(s);
- i는 복사를 시작할 위치를 나타내는 변수로, 처음에는 0부터 시작한다.
- n은 문자열 s의 길이를 나타낸다. 예를 들어, "emma"라면 n = 4이다.
- i < n + 1
- i가 n + 1보다 작은 동안 반복한다. 왜 n + 1일까?
문자열의 끝을 나타내는 널 종료 문자(\0)까지 복사해야 하기 때문이다. n이 4라면 n + 1은 5가 되고, i는 0부터 4까지 반복하면서 마지막 \0까지 복사한다.
- i가 n + 1보다 작은 동안 반복한다. 왜 n + 1일까?
- t[i] = s[i];
- s의 각 문자를 t에 복사한다. 첫 번째 반복에서는 s[0]을 t[0]에, 두 번째 반복에서는 s[1]을 t[1]에 복사한다. 이렇게 반복문이 끝나면 t는 s와 똑같은 문자열을 가지게 된다.
최종 결과
입력값 "emma"를 주었을 때:
- s는 원본 문자열인 "emma"로 그대로 남는다.
- t는 첫 번째 글자만 대문자로 바뀐 "Emma"가 된다.
이때 t[0] = toupper(t[0]);가 t의 첫 번째 문자를 대문자로 바꾼다. toupper() 함수는 알파벳을 대문자로 변환하는 함수로, t[0]이 e일 경우 t[0]을 E로 변경하게 된다.
왜 이렇게 중요한가?
이 과정을 이해하는 것은 C 언어에서 메모리 관리와 동적 메모리 할당의 중요성을 배우는 데 매우 중요하다. malloc을 사용하여 동적으로 메모리를 할당하고 문자열을 복사하는 방법을 배우면, 더 복잡한 프로그램에서도 유용하게 활용할 수 있기 때문이다.
이렇게 malloc과 for문을 이용하여 문자열을 정확히 복사하는 방법을 배웠다✨. 이를 통해 문자열 복사와 메모리 관리에 대한 기본적인 이해를 쌓을 수 있어서 감사하다. C 언어를 배우는 과정에서 메모리의 중요성을 인식하고, 이를 어떻게 효율적으로 사용할지에 대한 감을 잡을 수 있을 테니까(:
'IT' 카테고리의 다른 글
스택과 힙의 차이점 이해하기: 포인터를 이용한 메모리 교환 방법 (0) | 2025.03.30 |
---|---|
C 언어 동적 메모리 할당 쉽게 이해하기 | malloc, free, valgrind 활용 (0) | 2025.03.30 |
C 언어에서 string이 없는 이유 – 문자열과 포인터의 관계 (0) | 2025.03.30 |
인터넷 속도 계산법 : 1Gbps, 100Mbps 다운로드 속도 비교 (0) | 2025.03.28 |
C 프로그래밍에서 16진수와 메모리 주소 이해하기: 포인터와 역참조까지 (0) | 2025.03.27 |
댓글
이 글 공유하기
다른 글
-
스택과 힙의 차이점 이해하기: 포인터를 이용한 메모리 교환 방법
스택과 힙의 차이점 이해하기: 포인터를 이용한 메모리 교환 방법
2025.03.30 -
C 언어 동적 메모리 할당 쉽게 이해하기 | malloc, free, valgrind 활용
C 언어 동적 메모리 할당 쉽게 이해하기 | malloc, free, valgrind 활용
2025.03.30 -
C 언어에서 string이 없는 이유 – 문자열과 포인터의 관계
C 언어에서 string이 없는 이유 – 문자열과 포인터의 관계
2025.03.30 -
인터넷 속도 계산법 : 1Gbps, 100Mbps 다운로드 속도 비교
인터넷 속도 계산법 : 1Gbps, 100Mbps 다운로드 속도 비교
2025.03.28