[CS50] 자료구조 - 연결 리스트 개념과 구현
TIL
복잡한 프로그램을 구현하다 보면 기본적인 포인터 구조만 이용해서 메모리를 관리하기에는 다소 번거로울 때가 많다.메모리를 좀 더 효율적으로 관리하고 사용할 수 있는 데이터 구조의 개념과 연결 리스트를 알아보자.데이터 구조란데이터 구조(Data Structure)는 우리가 컴퓨터 메모리를 더 효율적으로 관리하기 위해 새로 정의하는 구조체다.일종의 메모리 레이아웃, 또는 지도라고 생각할 수 있다. 데이터 구조 중 하나인 연결 리스트에 대해 알아보자. 연결 리스트의 개념배열의 한계배열에서는 각 인덱스의 값이 메모리상에서 연이어 저장되어 있다.배열: [1][2][3]주소: 100 104 108 ← 연속된 메모리하지만 꼭 그럴 필요가 있을까? 연결 리스트의 아이디어각 값이 메모리상의 여러 군데 나뉘어져 있다고 ..
[CS50] 배열의 크기 조정하기
TIL
컴퓨터 안의 메모리는 마치 사물함 같은 구조다.우리가 사용하고자 하는 사물함의 개수를 한 번 정한 이후에는, 공간이 모자란다고 해서 주변의 사물함을 마음대로 더 사용할 수는 없다.이미 다른 목적으로 사용되고 있을 수도 있기 때문이다. 이미 일정한 크기의 메모리가 할당되어 있는 상황에서 그 크기를 늘리는 일은 생각만큼 단순하지 않다.포인터와 malloc의 개념을 응용해서 이미 정의된 배열의 크기를 바꿔보자.배열의 크기 조정하기배열 크기를 늘리는 방법일정한 크기의 배열이 주어졌을 때, 그 크기를 키우려면 어떻게 해야 할까? 단순히 현재 배열이 저장되어 있는 메모리 위치의 바로 옆에 덧붙이면 될 것 같지만, 실제로는 다른 데이터가 저장되어 있을 확률이 높다.따라서 새로운 공간에 큰 크기의 메모리를 다시 할당하..
[CS50] 메모리 - 파일 입출력
TIL
사용자에게 입력을 받는 함수는 어떻게 구현할 수 있을까? 파일을 읽고 쓰는 방법을 알아보자. 메모리 구조를 다시 한 번 살펴보면,메모리 영역머신 코드: 프로그램이 컴파일된 바이너리글로벌: 프로그램 안에서 저장된 전역 변수힙: malloc으로 할당된 메모리의 데이터스택: 프로그램 내의 함수와 관련된 것들힙 영역에서는 malloc에 의해 메모리가 더 할당될수록 아래로 늘어나고, 스택 영역에서는 함수가 더 많이 호출될수록 위로 늘어난다. 제한된 메모리 용량 하에서 점점 늘어나다 보면 기존의 값을 침범하는 상황이 발생하는데, 이를 힙 오버플로우 또는 스택 오버플로우라고 한다. 사용자에게 입력 받기get_int 구현#include int main(void){ int x; printf("x: "); ..
[CS50] 메모리 - 메모리 교환, 스택, 힙
TIL
각각 사이다와 콜라가 들어있는 컵 두 개가 있을 때, 사이다와 콜라를 바꿔 담고 싶으면 어떻게 해야 할까?아마 교환을 도와줄 새로운 컵이 잠시 필요할 것이다. 메모리에 저장된 값들을 교환할 때도 이와 비슷하게 할 수 있을까?잘못된 값 교환다음 코드를 보자.#include void swap(int a, int b);int main(void){ int x = 1; int y = 2; printf("x is %i, y is %i\n", x, y); swap(x, y); printf("x is %i, y is %i\n", x, y);}void swap(int a, int b){ int tmp = a; a = b; b = tmp;}// 출력// x is 1, y is 2..
[CS50] 메모리 - 메모리 할당과 해제
TIL
메모리를 할당한 후에 저장한 값이 필요 없어지고 나면 어떻게 해야 할까?유한한 메모리를 효과적으로 관리하기 위해 할당한 메모리를 어떻게 관리해야 하는지 알아보자.메모리 해제의 필요성malloc 함수를 이용하여 메모리를 할당한 후에는 free 함수를 이용하여 메모리를 해제해야 한다.그렇지 않으면 메모리에 저장한 값은 쓰레기 값으로 남게 되어 메모리 용량의 낭비가 발생하는데, 이러한 현상을 메모리 누수(Memory Leak)라고 한다. 문제가 있는 코드다음 코드를 살펴보자.#include void f(void){ int *x = malloc(10 * sizeof(int)); x[10] = 0;}int main(void){ f(); return 0;}함수 f는 포인터 x에 int형의 크기..
[CS50] 메모리 - 문자열 복사
TIL
이미 저장되어 있는 문자열을 다른 곳에 복사하려면 어떻게 해야 할까? 문자열을 복사하는 방법과 주의사항을 알아보자.잘못된 문자열 복사문자열을 복사하기 위해 아래 코드를 실행해보자.#include #include #include 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: Emmat: Emmas 변수에는 'emma'라는 문자열이 아닌 그 문자열이 있는 메모리 주소가 저장된다. string s는 char *s와 동일한 의미이므로, t도 s와 동일한 주소를 가리킨다. 그렇기 때문..
[CS50] 메모리 - 문자열 비교
TIL
두 문자열이 같은 내용을 담고 있는지는 어떻게 비교할 수 있을까?문자열이 저장되어 있는 방식을 들여다보며, 문자열을 직접 비교하는 것이 가능한지 알아보자.문자열의 메모리 주소#include int main(void){ char *s = "EMMA"; printf("%p\n", s); // "E"의 메모리 주소}이 코드는 포인터 s의 값을 출력한다. 즉, "EMMA"라는 문자열의 가장 첫 번째 값인 "E"에 해당하는 메모리 주소를 출력한다. 각 문자의 주소printf("%p\n", &s[0]); // "E"의 메모리 주소printf("%p\n", &s[1]); // "M"의 메모리 주소printf("%p\n", &s[2]); // "M"의 메모리 주소printf("%p\n", ..
[CS50] 메모리 - 문자열과 메모리
TIL
우리는 이전에 string이라는 자료형을 사용했지만, 이는 실제로 C에서 존재하지 않는 자료형이다.문자열이 실제로 메모리상에 어떻게 저장되어 있는지, 문자열을 손쉽게 저장하고 접근하기 위한 방법을 배워보자.문자열의 정체지금까지 문자열을 저장하기 위해 CS50 라이브러리에 포함된 string 자료형을 사용했다.string s = "EMMA"; 문자열은 결국 문자의 배열이다. s[0], s[1], s[2], ...와 같이 하나의 문자가 배열의 한 부분을 나타낸다. 가장 마지막의 \0은 0으로 이루어진 바이트로, 문자열의 끝을 표시하는 약속이다.변수 s는 결국 이러한 문자열을 가리키는 포인터가 된다.더 정확히는 문자열의 가장 첫 번째 문자, 즉 주소 0x123에 있는 s[0]을 가리킨다. string의 정의실..
[CS50] 메모리 - 포인터
TIL
메모리 주소를 직접 관리하는 것은 쉽지 않기 때문에, C에서는 포인터라는 개념을 통해 변수의 주소를 쉽게 저장하고 접근할 수 있다. 포인터에 대해 알아보자.포인터 변수* 연산자는 어떤 메모리 주소에 있는 값을 받아오게 해준다. 이 연산자를 이용해 포인터 역할을 하는 변수를 선언할 수 있다.#include int main(void){ int n = 50; int *p = &n; printf("%p\n", p); printf("%i\n", *p);}// 출력 예시// 0x7ffe00b3adbc// 50int n = 50; - 정수형 변수 n에 50 저장int *p = &n; - 포인터 변수 p에 변수 n의 주소 저장printf("%p\n", p); - 포인터 p의 값(변수 n의 주소) ..
[CS50] 메모리 - 메모리 주소
TIL
메모리 주소C로 작성한 변수들은 실제로 컴퓨터 메모리에 어떻게 저장될까? 메모리 주소를 나타내는 방법과 그 주소를 알아내는 방법, 그 주소에 찾아가는 방법을 알아보자. 16진수컴퓨터 과학에서는 숫자를 10진수나 2진수 대신 16진수(Hexadecimal)로 표현하는 경우가 많다. 16진수를 사용하면 10진수보다 2진수를 나타내기가 더 편리하기 때문이다.10진수를 16진수로 바꾸기JPG 이미지 파일은 항상 255 216 255로 시작하는데, 이것은 10진수다. 하지만 컴퓨터는 0과 1만 이해할 수 있기 때문에 실제로는 10진수를 사용하지 않는다.16진수에서는 10부터 15까지를 a - f로 표현한다. 그리고 0x를 붙여 뒤에 오는 문자들이 16진수임을 알린다. 변환 예시:15: 0x0f16: 0x1017:..