1. 문자열
* 문자열
- cs50수업을 듣는 동안 string 자료형을 사용하기 위해서 cs50라이브러리를 사용했다.
- 이 때의 문자열은 문자의 배열이므로 다음과 같이 메모리에 저장된다. (종단문자포함)
- 실제로 c언어에는 string이라는 별도의 자료형은 존재하지 않으며, cs50라이브러리에서는 string을 다음과 같이 정의해두었다.
typedef char *string
- 따라서 string타입의 정의 없이 문자열을 출력하려면 다음과 같이 작성한다.
#include <stdio.h>
int main(void)
{
char *s = "HARRY";
printf("%s\n", s); // HARRY
printf("%p\n", s); // 0x402002
}
- 이 때 포인터를 출력하면 문자열의 가장 첫 값인 H에 해당하는 메모리 주소를 보여준다.
- 실제로 포인터는 첫번째 값의 주소만 알고 있다가 문자열을 부르면 종단문자가 나올 때 까지 반환한다.
printf("%c\n", *s);
printf("%c\n", *(s+1));
printf("%c\n", *(s+2));
printf("%c\n", *(s+3));
printf("%c\n", *(s+4));
- 위와 같은 방식을 사용하면 문자를 하나씩 출력할 수 있다. 마치 인덱스처럼말이다.
* 문자열 복사
#include <cs50.h>
#include <ctype.h>
#include <stdio.h>
int main(void)
{
string s = get_string("s: "); //s : harry
string t = s;
t[0] = toupper(t[0]);
printf("s: %s\n", s); //Harry
printf("t: %s\n", t); //Harry
}
- 위와 같이 t에 s를 복사하면 문자열이 아닌 주소가 저장된다. 왜냐하면 string은 char *s와 동일하기 때문이다. 따라서 t를 변경하면 s도 함께 변경된다.
- 메모리상에서 실제로 복사를 행하려면 어떻게 해야할지 아래에서부터 알아보자.
2. 메모리
* 메모리 할당
- 위의 상황에서 가장 먼저 해야할 일은 t가 가질 문자열만큼의 메모리를 할당시켜줘야 한다.
- 이 때 메모리를 할당하기 위해서 malloc이라는 함수를 사용한다.
#include <cs50.h>
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(void)
{
char *s = get_string("s: "); // s: harry
char *t = malloc(strlen(s) + 1);
for (int i = 0, n = strlen(s); i < n + 1; i++)
{
t[i] = s[i];
}
t[0] = toupper(t[0]);
printf("s: %s\n", s); // s: harry
printf("t: %s\n", t); // t: Harry
}
- malloc(memory allocation)은 정해진 크기 만큼 메모리를 할당한다. 따라서 문자열의 길이에 종단문자 길이를 더한 만큼 인자로 작성하였다.
- 이제 루프를 종단문자까지 돌면서 복사를 진행한다.
- 결과를 보면 알 수 있듯이 t에 toupper을 하여도 s에는 영향이 없다.
* 메모리 할당과 해제
- 위에서 만든 코드에는 사실 문제가 있다.
- malloc함수를 이용해서 메모리를 할당했다면 반드시 free라는 함수로 메모리를 해제해야한다. 그렇지 않으면 메모리에 저장한 값은 쓰레기 값으로 남게 되어 '메모리 누수'가 발생한다.
- malloc함수로 메모리를 할당하면 힙 메모리에 남아 있으며, 함수가 끝나더라도 해제가 되지 않는다. main함수가 끝나도 유지되어야 하는 경우라 하더라도 밖에서 free는 해줘야한다.
- 물론 OS에서 프로그램 종료시에 사용한 메모리를 해제해준다고는 하나 OS에 의존하는 것은 좋지 못한 습관이다.
- 따라서 위의 함수의 끝에 free(t) 를 작성하면 올바르게 프로그램이 종료될 것이다.
- 참고로 위에서 할당한 메모리를 벗어난 인덱스에 값을 할당함녀 버퍼 오버플로우가 발생한다.
참고
이 글은 하버드 대학교 David Malan 교수의 CS50 강의를 수강 후 정리하며 쓴 글입니다. 코드는 C언어로 작성되었으며, 개발환경은 CS50 IDE에 최적화되어 있습니다. 일부 라이브러리는 다른 환경에서 별도의 설정이 필요할 수 있습니다.
CS50 공식사이트
부스트코스
CS50 IDE
'Computer Science > Computer Organization' 카테고리의 다른 글
<메모리> V8 엔진의 메모리 (2) | 2021.08.17 |
---|---|
<컴퓨터 구조> 메모리 교환, 스택, 힙 (0) | 2021.02.19 |
<메모리> 메모리와 포인터 (0) | 2021.02.17 |
<컴퓨터 구조> 컴파일링과 디버깅 (0) | 2021.01.27 |
<컴퓨터 구조> 하드웨어의 한계 (0) | 2021.01.20 |