본문 바로가기

Programming/C

(20)
C 언어 | 배열의 크기 조정하기 학습 목표 배열의 크기를 조정하는 코드를 작성할 수 있다. 컴퓨터 안의 메모리는 마치 사물함과 같다. 한 번 사물함의 개수를 정한 이후에는 공간이 모자란다고 해서 주변의 사물함을 마음대로 더 사용할 수 없다. 배열을 정의할 때도 마찬가지다. 이미 일정한 크기가 할당되어 있는 상황에서 그 크기를 늘리는 일은 단순하지 않다. 배열의 크기 조정하기 1. for 루프를 사용해 값 복사 배열의 크기를 키워야 한다면 어떻게 해야 할까. 배열이 저장된 메모리 위치 옆에 메모리를 덧붙이자 생각할 수 있지만, 그곳에는 다른 데이터가 저장돼 있을 수 있다. 따라서 안전하게 배열의 크기를 키우기 위해서는 새로운 공간에 큰 크기의 메모리를 다시 할당하고 배열의 값을 하나씩 옮겨줘야 한다. 이 과정은 배열의 크기(n)만큼 시간..
C 언어 | malloc과 포인터 학습 목표 포인터의 개념과 malloc 함수의 용법을 잘 이해할 수 있다. 6주 차부터는 C로 구현할 수 있는 다양한 데이터 구조를 배운다. 데이터 구조를 정의하고 관리하기에 앞서 메모리와 포인터에 대한 개념을 정확히 이해해야 한다. malloc과 포인터 지난 포스팅의 malloc 함수와 포인터를 복습하는 예제를 보자. 코드를 살펴보자. main 함수에서 먼저 포인터 x와 y를 선언한다. x에 malloc 함수를 이용해 int 자료형에 해당하는 메모리를 할당한다. x와 y 포인터가 가리키는 지점에 각각 정수를 저장한다. 코드에는 한 가지 오류가 있다. 프로그램을 실행시켜보자. 에러를 보면 포인터 y에 문제가 있음을 알 수 있다. y는 포인터로 선언되었을 뿐이지 x처럼 메모리를 할당받지 못했다. 어디를 가..
C 언어 | 파일 쓰기와 읽기 학습 목표 사용자로부터 값을 입력받아 파일에 출력하는 프로그램을 작성할 수 있다. 사용자에게 입력받기 앞 포스팅에서 메모리 영역 중 스택은 함수 호출과 관련된 변수가 저장된다고 배웠다. 이는 이제껏 자주 사용했던 get_int()나 get_string과 같은 함수에서도 사용된다. get_int()와 get_string() 함수를 직접 구현해보자. 코드를 살펴보자. line 7을 보면 scanf() 함수가 쓰인 것을 확인할 수 있다. scanf() 함수는 사용자로부터 형식 지정자에 해당하는 값을 받고 저장한다. 실제 스택 영역 안에 변수가 저장된 주소로 찾아가야 하기 때문에 x가 아닌 &x라 입력한다. get_string() 함수를 구현한 경우 s를 배열로 정의했기 때문에 그대로 s를 입력해 첫 바이트의 ..
C 언어 | 메모리 교환, 스택, 힙 학습 목표 메모리에 저장된 두 값을 교환하는 코드를 작성할 수 있다. 메모리 교환 입력값을 바꾸는 함수를 만들어 프로그램을 작성해보자. #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; } 프로그램을 살펴보자. 정수 a와 b를 입력받아 값을 바꾸는 swap() 함수를 만들었다. swap() 함수는 같은 정수형 변수 tmp를 사용해 값을 바꾼다. main 함수에서 swap() 함수..
C 언어 | 메모리 할당과 해제 학습 목표 메모리를 할당하고 해제할 수 있다. 메모리 할당과 해제 malloc() 함수를 이용하여 메모리를 할당한 경우 저장한 값이 필요가 없어지면 쓰레기 값으로 남는다. 이를 메모리 누수(memory leak)라고 한다. 메모리 누수를 방지하기 위해서는 free() 함수를 이용해 메모리를 해제해줘야 한다. 메모리 누수에 관련된 예제를 보자. 프로그램을 살펴보자. f 함수를 보면 포인터 x에 malloc() 함수를 사용해 메모리를 할당한다. 메모리의 크기는 int 형(4바이트)의 10배로 40바이트를 할당한다. x의 10번째 인덱스에는 0을 할당한다. main 함수에서는 f 함수를 실행시키고 0을 반환한다. 이 프로그램의 메모리 누수를 확인해보자. valgrind라는 메모리 누수 확인 프로그램을 사용하면..
C 언어 | 문자열의 복사 학습 목표 문자열을 복사할 수 있다. 문자열의 복사 문자열을 복사하는 코드를 만들어보자. #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); } 사용자에게 입력값 s("emma")를 받고, t에 복사 후 첫 문자를 대문자로 바꾸는 프로그램을 만들고자 했다. 하지만 계획과 다르게 toupper()함수가 s와 t 모두에 영향을 주어 "Emma"가 출력되었다. * toupper() 함수를 사용하기 위해 ctype 라이브러리를 추가했다. 이유는 다음과 같다. cs50 라이브러리에서 string은..
C 언어 | 문자열의 비교 학습 목표 문자열이 저장되어 있는 방식에 근거해서 문자열을 비교하는 방법에 대해 설명할 수 있다. 문자열의 출력 문자열의 주소를 출력하는 예시를 다시 보자. #include int main(void) { char *s = "EMMA"; printf("%p\n",s); } 앞선 강의에서 문자열의 주소는 s라는 포인터의 값, 즉 문자열의 가장 첫 값인 s[0]의 메모리 주소를 출력한다 배웠다. 그렇다면 아래 코드가 무엇을 출력하는지 보자. printf("%p\n", &s[0]); printf("%p\n", &s[1]); printf("%p\n", &s[2]); printf("%p\n", &s[3]); 위의 예제에 코드를 추가(8-11)한 모습이다. 명령 프롬프트로 부터 알 수 있는 것은 다음과 같다. &s[..
C 언어 | 문자열과 포인터 이제껏 문자열을 저장하기 위해 CS50 라이브러리에 포함된 string 자료형을 사용했다. 하지만 이는 실제 C에서는 존재하지 않는 자료형이다. 학습 목표 문자열 형태의 새로운 자료형인 string이 어떻게 정의되었는지 설명할 수 있다. 문자열과 포인터 변수 s에 "EMMA"라는 값을 저장하는 프로그램을 예로 들어보자. #include #include int main(void) { string s = "EMMA"; printf("%s\n",s); } cs50 라이브러리를 사용해, 즉 string 타입을 사용해 값을 출력한 모습이다. 프로그램을 설명하자면 다음과 같다. "EMMA"는 문자의 배열이고 s[0]=E, s[1]=M과 같이 하나씩 표현될 수 있다. 문자의 마지막인 s[4]는 \0로, 0으로 이루어..