1. malloc과 포인터 복습 int main(void){ int *x, *y; x = (int*)malloc(sizeof(int)); *x=42; //동적할당받은 메모리에 저장 *y=13; //가리키는 메모리공간이 없으므로 error! } ✔ 포인터로 선언만 되었고, 어디를 가리킬지에 대해 정의되지 않았으므로 오류가 발생한다 2. 배열의 크기 조정하기 #include #include int main(void){ int* listA = (int*)malloc(sizeof(int)*3); if(listA == NULL) return 1; listA[0] = 1; listA[1] = 2; listA[2] = 3; //listA보다 큰 동적메모리 할당받기 int* listB = (int*)malloc(siz..
8-9. 파일 쓰기/파일 읽기 힙 오버플로우와 스택 오버플로우 ✔ heap 영역에서는 malloc()에 의해 메모리가 할당될수록, 점점 사용하는 메모리가 아래로 늘어난다. ✔ stack 영역에서는 함수가 호출될수록, 점점 사용하는 메모리가 위로 늘어난다. ✔ 어느 순간 제한된 메모리 내에서 기존의 값을 서로 침범하는 상황이 발생할 수도 있다. ✔ 이런 상황을 힙 오버플로우 또는 스택 오버플로우라고 말한다. ✔ 컴퓨터가 너무 많은 메모리를 사용하면 파일이나 사진이 열리지 않거나 화면이 정지하거나 하는 상황이 발생한다. ✔ 이런 상황은 버퍼 오버플로우라고 한다. 배열의 이름과 포인터 #include int main(void){ char *str = NULL; scanf("%s",str2); printf("%..
7. 메모리 교환, 스택, 힙 heap과 stack machine code ✔ 프로그램 시작 → 메모리 가장 위에 머신 코드가 올라간다. globals ✔ 프로그램이 사용하는 전역변수나 값은 machine code의 바로 아래 공간을 사용한다. heap ↓ ✔ malloc() 호출 시, heap에서 메모리를 가져와 할당받는다. ✔ 위에서 아래로 쌓인다. ↑ stack ✔ 함수를 호출할 때마다, 함수의 인자와 지역변수는 stack 공간에 위치한다. ✔ 호출된 함수는 명령문을 모두 실행하면 함수를 다시 호출하지 않는 이상 작동하지 않는다. ✔ stack은 메모리의 가장 아래 영역에 위치한다 ✔ 아래에서 위로 쌓인다 stack #include void swap(int a, int b); int main(voi..
6. 메모리 할당과 해제 ✔ malloc 함수를 이용하면 메모리 할당이 가능하다 ✔ 할당된 메모리를 모두 사용한 후에는 반드시 free라는 함수를 사용해 메모리를 해제해주어야한다 ✔ 그렇지 않으면 메모리에 저장한 값이 쓰레기 값으로 남아 메모리 용량의 낭비가 발생하기 때문 ✔ 이러한 현상을 메모리 누수라고 한다 버퍼 오버플로우 할당받은 메모리를 초과하는 메모리를 사용하고자 할 때 발생하는 메모리 누수 #include #include int main(void) { int *x = malloc(10 * sizeof(int)); x[10] = 0; //버퍼 오버플로우 발생 free(x); return 0; } ✔ 배열 x 에는 정수형 값을 총 10개 저장할 수 있다. ✔ 배열의 index는 0부터 시작되므로,..
3. 문자열 문자열은 문자의 배열이고, 배열 마지막에는 문자열의 끝을 나타내는 \0(null 종단 문자)이 저장된다. 문자열을 출력하기 위해서는 포인터(*)를 사용해야 한다. char형 배열의 이름은 결국 문자열을 가리키는 포인터가 된다. 말하자면 C언어에서는 string을 char *이라고 말한다고 볼 수 있다. #include int main(void){ char *str = "Hello World"; printf("%s\n", str); return 0; } 4. 문자열 비교 문자의 배열의 이름은 문자열을 가리키는 포인터인데, 더 상세하게 말하면 배열에 저장된 첫 번째 문자를 가리킨다. 배열에 저장된 문자 하나하나의 주소를 확인해보자. #include int main(void) { char *s =..
2. 포인터 * 를 사용해 그 메모리 주소의 실제 값을 얻어올 수도 있으며, ~의 주소로 이동해달라는 의미를 가진다. 이 연산자를 사용해 포인터 역할을 하는 포인터 변수를 선언할 수 도 있다. #include int main(void) { int n = 50; int *p = &n; printf("%p\n", p);//0x7ffd9792ee98 printf("%d\n", *p);//50 return 0; } 첫 번째 출력 함수에서는 형식 지정자 % p를 사용해 포인터 변수 *p 저장된 주소를 출력했다. 두 번째 출력 함수에서는 포인터 변수 *p에 저장된 주소로 이동해서 n에 저장된 값을 형식 지정자 % d를 통해 받아와 출력했다. 즉, 포인터 변수를 사용해 포인터 변수에 저장된 주소를 출력하거나, 포인터..
1. 메모리 주소 16진수의 유용성 10진수 255 216 255 2진수 1111 1111 1101 1000 1111 1111 16진수 0xff 0xd8 0xff 컴퓨터 과학에서는 숫자를 2진수 대신 16진수로 표현하는 경우가 많다. 2진법으로 표현할 때에는 너무 길어진 데이터를 16진수로는 간단하게 표현할 수 있기 때문이다. 2^4 는16이므로, 4비트씩 두 덩어리로 나누어보면 0000부터 1111까지 16진수로 간단하게 표현할 수 있음을 알 수 있다. 이처럼 데이터 처리할 때 장점이 많기 때문에 16진수를 사용해 숫자를 표현하는 경우가 많다. 메모리 주소 C언어에서는 변수의 메모리 상 주소를 받기위해 & 연산자를 사용한다. & 연산자를 통해 변수의 메모리상 주소에 값을 저장하기도 하고, 실제 주소값을..
1. 검색 알고리즘 배열은 한 자료형의 여러 값들이 모여있는 구조. 배열 안에 있는 어떤 값을 찾기 위해서는 선형 검색, 이진 검색 등의 검색 알고리즘을 사용. ✔ 선형 검색 : 배열의 인덱스를 처음부터 끝까지 하나하나 증가시키면서 방문하여 그 값이 속하는지 확인 (a to z) ✔ 이진 검색 : 정렬된 배열이라면, 배열 중간 인덱스부터 시작하여 비교, 다시 중간 인덱스부터 비교를 반복 2. 알고리즘 표기법 Big O 표기법 ✔ Big O 는 알고리즘 실행시간의 상한을 의미한다 ✔ 선형 검색에서는 n개의 항목이 있을 때, 최대 n번의 검색을 해야 하므로 상한이 Big O(n) 이 된다 ✔ 이진 검색은 (이미 정렬된 데이터의 경우) 선형 검색보다 빠르고, 1번 이상의 검색을 해야 하므로상한이 Big O(l..
1. 컴파일링 컴파일링의 과정 : preprocessing → compiling → assembling → linking ✔ 전처리(preprocessing) : 실질적인 컴파일 전에 헤더 파일 추가 ✔ 컴파일(compiling) : 전처리한 코드를 컴퓨터가 이해할 수 있는 어셈블리어라는 저수준 프로그래밍 언어로 컴파일 ✔ 어셈블링(assembling) :: 어셈플리코드를 중앙처리장치가 프로그래밍을 수행할 수 있도록, 연속된 0과 1로 변경 ✔ 링커(링크) : 여러개의 파일을 하나의 오브젝트 파일로 합쳐야 할 때 필요한 단계 (컴파일을 하나만 해야 하면 진행 X) 2. 디버깅 버그와 디버깅 ✔ 버그 : 코드에 들어있는 오류 ✔ 디버깅 : 모드에 있는 버그를 식별하고 고치는 과정 디버거 ✔ 프로그래머들이 ..