본문 바로가기

컴퓨터 공학231

[ C ] 문자열 함수 이해하기3_문자 단위 입출력 함수_putchar, fputc, getchar, fgetc / EOF 이란 C언어 문법 문자 단위 입출력 함수_putchar, fputc, getchar, fgetc, EOF ■ 문자 출력 함수: putchar, fputc 모니터로 하나의 문자를 출력할 때 일반적으로 다음 두 함수를 사용합니다. #include int putchar(int c); int fputc(int c, FILE * stream); /* 함수 호출 실패 시 EOF 반환 */ putchar 함수는 인자로 전달된 문자를 stdout으로 표현되는 표준 출력 스트림으로 전송하는 함수입니다. fputc 역시 같은 역할이며, 두번째 인자로 스트림을 지정할 수 있다는 차이가 있습니다. ■ 문자 입력 함수: getchar, fgetc 키보드로 하나의 문자를 입력할 때 일반적으로 다음 두 함수를 사용합니다. #includ.. 2020. 7. 21.

[ C ] 문자열 함수 이해하기2_스트림과 데이터의 이동 C언어 문법 스트림과 데이터의 이동 ■ 데이터의 입출력 프로그램 중심으로 데이터가 프로그램 안으로 들어오면 입력이고, 프로그램 밖으로 나가면 출력입니다. 대표적인 입력 장치로는 키보드가 있으며, 파일도 입력의 대상이 될 수 있습니다. 대표적인 출력 장치로는 모니터가 있으며, 파일도 출력의 대상이 될 수 있습니다. ■ 스트림(stream)이란? 이제까지 C언어로 코드를 작성하고 결과값을 어떻게 출력했나요? printf 함수를 호출하였습니다. 프로그램과 키보드는 서로 떨어져 있는 개체인데 printf 함수 호출만으로 어떻게 문자열이 출력될 수 있을까요? 프로그램과 키보드를 연결해주는 다리가 있기 때문입니다. 그 역할을 하는 매개체를 '스트림'이라고 합니다. 스트림이란 운영체제에서 제공하는 가상의 다리입니다... 2020. 7. 21.

[ C ] 문자열 함수 이해하기1_C 스타일 문자열이란? / 문자열 길이 구하기 C언어 문법 C 스타일 문자열이란? ■ C 스타일 문자열 개념 기본 자료형 배울 때 가장 먼저 언급하는 부분이 그 자료형의 크기(표현할 수 있는 범위)입니다. 기본 자료형의 크기는 특정 플랫폼마다 항상 고정되어 있습니다. int num = 4 // 4바이트 (32bit) double num2 = 1.2 //8바이트 (64bit) 이런 식으로 말이죠. 그럼 다음 문장을 대입할 변수 크기는 얼마로 설정하면 될까요? "I have no idea at all" 일단 저장하고 싶은 데이터는 문장입니다. 여러 문자가 모인 문자열인거죠. 다른 프로그래밍 언어를 배운적이 있는 분이라면 문자열을 표현할 수 있는 자료형 Stirng(JAVA) 생각날 수도 있을 것입니다. 하지만 C언어에는 문자열을 표현할 수 있는 따로 자.. 2020. 7. 21.

C언어 문법 총정리_프로그래밍 독학이나 컴퓨터공학과를 준비하는 분을 위한 C언어 독학이나 컴퓨터공학과를 준비하는 자를 위한 예습용, 복습용 C언어 문법 총 정리 학습자료: 윤성우 열혈C프로그래밍, 포프 C 언매니지드프로그래밍 ■ C 언어를 배워야 하는 이유 '머신러닝은 파이썬, 데이터 통계는 R'이라고 주장하며 '00일만에 개발자 되기'를 광고하는 일명 코딩 교육 사이트들이 많습니다. 또한 C언어는 옛날 언어라며 그런 언매니지드(unmanaged) 언어는 가까운 미래에 더이상 쓰이질 않을 것이라고 합니다. 하지만 이 모든 주장들은 사실은 아닙니다. C언어는 TIOBE 지수(프로그래밍 언어 순위)로 2019년에는 2위였다가 현재 2020년은 1위 입니다. 티오베 사이트 : tiobe.com/tiobe-index/ C언어는 2001년 이후 언제나 1위 아니면 2위했던 언어입니다... 2020. 7. 21.

[ C ] 포인터 이해하기11_포인터 개념 정리 / 용도 / 복습 또 복습하기 C언어 포인터 개념 정리 / 용도 / 복습 또 복습하기 복습 또 복습합시다. ■ 포인터의 용도 1 큰 데이터를 매개변수로 전달할 수 있습니다. 배열 같은 경우 데이터를 하나하나씩 복사하려면 힘듭니다. const 배열에 요소가 10개정도 있으면 괜찮지만 요소가 한 10만개라면 일일히 복사하는 것은 정말 시간 낭비입니다. 그래서 배열을 매개변수로 전달하여 첫 번째 요소의 주소를 전달하므로 쉽게 데이터를 처리할 수 있게 됩니다. 2 반환 값이 둘 이상일 때 사용할 수 있습니다. C언어에서는 반환값 2개를 return 할 수 없습니다. 따라서 반환해야할 값이 여러 개 있다면 매개변수로 포인터를 넣으면 됩니다. 그럼 함수 안에서 원본을 직접 변경할 수 있습니다. 이런 변수를 인앤아웃(in&out) 변수라고 합니다.. 2020. 7. 21.

[ C ] 포인터 이해하기10_다중, 이중 포인터란? / 다중 포인터 사용하는 이유 다중, 이중 포인터란? / 다중 포인터 사용하는 이유 ■ 이중 포인터란? 포인터는 무엇인가요? 주소를 저장하는 변수입니다. 그럼 그 번수의 주소를 또 저장할 수 있을까요? 10이라는 데이터가 저장되어 있다고 합시다. 저장된 곳의 주소가 있겠지요. 그 주소가 또 다른 곳에 저장되어 있다면요? 다음과 같은 그림이 그려지겠네요. 주소를 저장한 변수의 주소는 어디에 저장할까요? 주소를 저장하니까 포인터네요. 그럼 그 포인터의 데이터형은 뭔가요? 그 역시 어떤 것의 주소이므로 포인터입니다. 이런 식으로 포인터 변수의 주소를 저장하는 변수를 이중 포인터라고 합니다. int num = 10; // int형 변수 num 선언하고 10대입 int* p = # // int형 포인터 p선언하고 num 주소값 대입 i.. 2020. 7. 21.

[ C ] 포인터 이해하기9_포인터 배열, 2차원 배열이란? 예제코드로 개념이해하기 포인터 배열이란? 2차원 배열이란? 예제로 개념이해하기 ■ 포인터 배열 포인터도 변수이기 때문에 포인터를 저장하는 배열도 있습니다. 그럼 포인터 배열은 어떻게 선언해야 할까요? 일반적인 배열은 아래와 같이 선언합니다. 예) int nums[3]; // 자료형 배열명[요소 수] int형 데이터를 넣을 수 있는 배열이지요. 그럼 포인터를 저장하는 배열은 데이터형을 포인터형으로 하면 됩니다. 예) int* num_pointers[3]; int*를 담는 배열입니다. 포인터 배열 [ 예제 코드 ] int nums1[3] = { 11, 22, 33 }; int nums2[1] = { 90 }; int nums3[4] = { 36, 25, 45, 78 }; int* num_pointers[3]; num_pointer.. 2020. 7. 20.

[ C ] 포인터 이해하기8_함수 포인터 쉽게 읽는 방법 함수 포인터 쉽게 읽는 방법 ■ 함수의 포인터 읽는 순서 함수 포인터 읽는 방법을 오른쪽-왼쪽으로 읽는다고 Right-Left Rule이라고도 합니다. 사실 영어권에서 통하는 rule이라 한국어로는 어순이 다르지만 한 번 알아두시면 편하니 천천히 익혀보시기 바랍니다. 아래의 함수 포인터를 읽어봅시다. double (*func) (double, double) ' 변수 func는 두 개의 double 형 매개변수를 받고 double 형을 반환하는 함수의 포인터입니다. ' 라고 읽으면 되는데, 읽는 순서를 아래 그림을 통해 알아봅시다. ■ 함수의 포인터 읽는 연습하기 ( 답은 드래그하면 확인할 수 있습니다.) double (*sort_arr) (double, double, double) 변수 func은 dou.. 2020. 7. 20.

[ C ] 포인터 이해하기7_함수 포인터란? 함수를 포인터에 저장할 수 있을까? 함수 포인터란? 함수 포인터 선언 방법 ■ 함수 포인터 개념 어셈블리어에서 어떤 함수를 호출하면 사실상 그 함수의 주소로 이동합니다. 함수의 주소는 컴파일 중 이미 정해지므로, 호출 시 실행됩니다. 물론 함수에서 반환할 때 돌아가야 하는 '호출자' 처럼 실행 중에도 바뀌는 코드도 있습니다. 그럼 이제까지 함수를 어떻게 호출했나요? 그렇죠. 함수의 이름을 사용했습니다. 배열의 이름이 배열의 시작주소 값을 의미하듯. 함수의 이름도 함수가 저장된 메모리 공간의 주소 값을 의미합니다. 이러한 함수의 주소 값을 저장하는 포인터 변수를 '함수 포인터'라고 합니다. ■ 함수 포인터 선언 그럼 함수 포인터 선언은 어떻게 해야할까요? operator라는 함수를 cal라는 함수의 매개변수로 사용한다고 할 때 다음과 같은 .. 2020. 7. 20.

[ C ] 포인터 이해하기6_void 포인터 개념 / 활용도 void 포인터 개념 / 활용도 자료형이 정해지지 않은 포인터를 void 포인터라고 합니다. 기본적으로 C언어는 자료형이 다른 포인터끼리 메모리 주소를 저장하면 컴파일 에러가 뜨지만 void 포인터는 자료형이 정해지지 않기 때문에 모든 자료형의 포인터를 저장할 수 있습니다. 함수, void 포인터 다 가능합니다. 그래서 void 포인터는 범용 포인터라고 합니다. int main() { int num1 = 10; int *numPtr1 = &num1; void *ptr; // void 포인터 선언 // 포인터 자료형이 달라도 컴파일 경고가 발생하지 않음 ptr = numPtr1; // void 포인터에 int 포인터 저장 // 포인터 자료형이 달라도 컴파일 경고가 발생하지 않음 numPtr1 = ptr; .. 2020. 7. 19.

[ C ] 포인터 이해하기5_값과 주소를 보호하는 const/const 읽는 방법 값과 주소를 보호하는 const/const 읽는 방법 변수를 상수화하는 방법 중 하나는 const 선언입니다 포인터 변수에도 똑같이 적용할 수 있습니다. 하지만 포인터의 const는 매우 헷갈립니다. 이유는 const로 값과 주소, 두 개를 보호할 수 있기 때문인데요. 키워드 선언 위치에 따라 보호할 대상과 읽는 방법이 달라지니 주의하셔야 합니다. 그럼 먼저 const로 보호할 수 있는 대상을 하나씩 보겠습니다. 1. 주소를 보호하는 const 포인터 기본 자료형 변수에 const를 붙이면 그 변수에 저장한 값을 변경할 수 없습니다. 그럼 포인터 변수에 const를 붙이면 무엇이 바뀌지 말아야 할까요? 포인터 변수에 저장되어 있는 것은? 메모리 주소 즉, const 포인터는 메모리 주소를 바꿀 수 없습니.. 2020. 7. 19.

[ C ] 포인터 이해하기4_값에 의한 전달 vs 참조에 의한 전달/from 윤성우 or 포프 값에 의한 전달 vs 참조에 의한 전달 / from 윤성우 or 포프 함수를 호출할 때 단순히 값을 전달하는 형태의 함수호출을 가리켜 Call-by-value라 하고, 메모리의 접근에 사용되는 주소 값을 전달하는 형태의 함수호출을 가리켜 Call-by-reference라 합니다. 그럼 매개변수로 배열을 전달하는 경우는 어느 쪽이라고 말할 수 있을까요? 1. 원본이 바뀌니까 참조에 의한 전달이다. 2. 아니다 메모리 주소를 복사했으니깐 결국은 값에 의한 전달이다. 엄밀히 말하면 C언어는 함수를 호출할 때 언제나 변수(그게 포인터든, 아니든)를 복사합니다. 즉, 매개변수로 들어온건 타입에 상관없이 복사를 할 뿐이니 값에 의한 전달이라고 말할 수 있습니다. 포인터를 사용한다는 것은 참조에 의한 전달을 흉내내기.. 2020. 7. 18.

[ C ] 포인터 이해하기3_포인터와 배열의 차이 포인터와 배열의 차이 포인터와 배열의 차이를 알아보기 전에 먼저 배열의 이름은 무엇을 의미하는지 알아보겠습니다. 배열의 이름은 포인터입니다. 단, 값 변경이 불가능한 상수 형태의 포인터입니다. 이해를 위해 예제를 보겠습니다. #include int main(void) { int arr[3] = {0, 1, 2}; printf("배열의 이름: %p \n", arr); printf("배열의 이름: %p \n", &arr[0]); printf("배열의 이름: %p \n", &arr[1]); printf("배열의 이름: %p \n", &arr[2]); //arr = &arr[i]; // 컴파일 오류 발생 return 0; } 위 코드를 통해 다음과 같은 사실들을 이끌어낼 수 있습니다. 1. &사용하면 주소값이 .. 2020. 7. 18.

[ C ] 포인터 이해하기2_참조와 역참조/ 역 참조 연산자 * 참조와 역참조/간접연산자/ 역 참조 연산자 * 포인터는 데이터가 저장된 주소값을 가리킵니다. 이것을 참조라고 합니다. 그럼 역 참조란 무엇일까요? 데이터가 저장된 주소로 가서 값에 접근하는 것을 말합니다. 값에 직접 접근하는게 아니라 주소를 이용해 간접적으로 접근합니다. 그래서 간접(indirect) 연산자라고도 합니다. 이제까지 함수에서 매개변수를 통해 인자를 전달하는 등 모든 데이터를 복사해서 썼다면 '역 참조'를 하면 원본에 접근가능합니다. 즉, 컴퓨터 구조에서(CPU든, 메모리든) 데이터를 오랫동안 메모리에 저장할 수 있습니다. 1 포인터가 저장하고 있는 메모리 위치로 간다 2 그곳에 저장된 값에 접근한다. (= 포인터가 가리키는 값에 접근하다) 역 참조 연산자 * ※ 곱하기.. 2020. 7. 18.

[ C ] 포인터 이해하기1_포인터 변수란?/선언 방법 / & 연산자 포인터 변수란?/선언 방법 / & 연산자 C언어는 하드웨어와 친합니다. 그래서 메모리에 접근할 수 있습니다. 이 점을 양날의 검처럼 잘 활용하면 강력한 일을 할 수 있고, 사고를 칠 수 있으니 잘 사용해야 합니다. 그럼 C언어는 어떻게 메모리에 접근할 수 있을까요? 바로 포인터를 이용하여 메모리에 직접 접근합니다. 이해를 위해 일단 변수 num1 에 데이터 10을 대입했다고 가정하겠습니다. 아래와 같은 그림이 그려지겠지요. int형 변수 num1은 Ox12FF76(주소)에 할당되어 있습니다. 그럼 코드상으로 어떻게 주소값을 알아낼 수 있을까요? 바로 주소 연산자 &( 비트 연산자 & 아님 ) 를 사용하면 됩니다. &는 피연산자의 주소 값을 반환하는 연산자입니다. 그래서 num1이란 변수가 있으면 &num.. 2020. 7. 17.

[ C ] 메모리 이해하기11_동적 메모리의 소유권 문제 동적 메모리의 소유권 문제 메모리에서 소유권 문제는 어떤 의미일까요? 바로 이미 할당된 메모리를 누가 해제를 해줘야 하는지에 관한 문제입니다. 해제는 꼭 소유주가 동적으로 할당한 메모리를 책임지고 해제로 마무리해야 합니다. 비소유자가 해제해도 문제입니다. 그럼 소유주란 누구일까요? 바로, 메모리를 생성한 함수입니다. 실제로 아래 함수을 호출 시 생기는 문제는 호출자가 이 함수를 호출할 때 함수 내부에서 새 메모리가 할당하여 반환한다는 사실을 어떻게 알아낼 수 있습니까? const char* combine_string(const char* a, const char* b) { void* str; char* p; /* a와 b의 길이 및 두 길이를 더한 값을 보관한 변수 생략 */ str = malloc(si.. 2020. 7. 17.

[ C ] 메모리 이해하기10 _정적 vs 동적 메모리 C언어 메모리 이해하기10 _정적 vs 동적 메모리 고정된 길이인 배열 동적 메모리를 사용하는 포인터 typedef struct { char firstname[NAME_LEN]; char lastname[NAME_LEN]; } name_fixed_t; typedef struct { char* firstname; char* lastname; } name_dynamic_t; 그대로 대입 가능 파일에 곧바로 저장 가능 memcpy()를 곧바로 사용가능 낭비하는 용량이 있음 메모리 할당/해제 속도 빠름 그대로 대입 불가 이 경우는 얕은 복사가 되어버림 파일에 곧바로 저장 불가능 memcpy() 곧바로 사용불가능 낭비하는 용량 없음 메모리 할당/해제 속도 느림 2020. 7. 17.

[ C ] 메모리 이해하기9 _realloc()의 메모리 누수 문제, 해결책은? C언어 메모리 이해하기9 _realloc()의 메모리 누수 문제 / 해결책 / malloc() + memcpy() +free() 먼저 realloc() 함수 개념을 이해하려면 이전 글을 읽어보세요. realloc() 함수란? void* realloc(void* ptr, size_t new_size); realloc() 에서는 메모리 누수가 날 수 있습니다. 메모리 누수가 생기는 예 void* nums; nums = malloc(SIZE); nums = realloc(nums, 2 * SIZE); //NULL 반환 위 경우 nums에 원래 저장되어 있던 주소가 사라집니다. NULL이 반환되었다는 것은 재할당에 실패했다는 뜻이고, 기존 메모리 역시 해제되지 않은 상태입니다. 이 상황에서 주소는 이미 잃어버렸.. 2020. 7. 16.

[ C ] 메모리 이해하기8 _calloc(), memset(), realloc() ■ calloc( ) void* calloc(size_t num, size_t size); 메모리 할당할 때 자료형의 크기(size)와 수(num)를 따로 지정하고, 모든 바이트를 0으로 초기화해주는 함수입니다. 어떤 단어의 약자인지는 의견이 분분합니다. counted alloc... clear alloc... C alloc... 이 함수는 잘 사용되지 않습니다. 그 이유는 malloc()과 memset()를 조합해서 사용하면 비슷하게 구현할 수 있기 때문입니다. memset()을 쓰면 0 외의 값으로도 초기화 가능한데 좀 더 자세한 점은 아래에서 다루겠습니다 ■ memset() void* memset(void* dest, int ch, size_t count); memory + set, 메모리를 어떤 .. 2020. 7. 16.

[ C ] 메모리 이해하기7 _malloc 짝꿍 함수 free 란? 메모리 관련 함수 malloc, free, C언어 예제 메모리 관련 함수에는 다음과 같은 것들이 있습니다. 이 글에서는 간단한 예제와 함께 malloc과 free함수에 대해 알아보겠습니다. 메모리 할당 및 해제 함수 : 동적에서만 사용할 수 있음 기타 메모리 관련 함수 : 동적이든 정적이든 다 쓰일 수 있음(포인터만 사용하면 되는거라) 할당 malloc() // memory + allocate 메모리 할당하다 calloc() 해제 free() // free 자유롭게하다 재할당 realloc() // re + allocate 다시 할당하다 memset() memcpy() memcmp() ■ malloc() void* malloc(size_t size); 동적으로 메모리를 할당하는 함수(힙 영역에 메모리를 .. 2020. 7. 16.

[ C ] 메모리 이해하기6 _동적메모리란? / 동적 할당 개념 그림으로 이해하기 동적메모리란? / 동적 할당 개념 그림으로 이해하기 프로그램이 동적 메모리를 가져다 사용할 때는 총 세 가지 단계를 거칩니다. 메모리 할당 메모리 사용 메모리 해제 매니지드 언어(대표적으로 C언어)는 위 3단계를 프로그래머가 직접 다 해야합니다. 1 . 메모리 할당 힙 관리자에게 메모리를 xxx 바이트만큼 달라고 요청합니다. 관리자는 그만큼의 연속된 메모리를 찾아서 반환합니다. 반환된 메모리는 어떤 자료형에 저장 가능할까요? 메모리 주소니 당연히 포인터입니다. 2. 메모리 사용 포인터 사용이랑 같습니다. 그래서 메모리를 원하는 대로 사용할 수 있습니다. 예) int 배열에 성적을 저장한 뒤 평균을 구해서 float 변수에 저장할 수 있습니다. 3. 메모리 반납/해제 힙 관리자에게 그 메모리 주소를 돌려주.. 2020. 7. 15.

[ C ] 메모리 이해하기5_힙(heap) 메모리란? 힙(heap) 메모리란? 힙메모리는 다음과 같은 스택 메모리의 단점을 보완합니다. ■ 스택 메모리의 단점 수명 함수가 반환되는 순간 그 안에 있던 데이터가 다 날아갑니다. 전역 변수는 언제나 살아있고, 지역 변수는 함수 안에서만 유효합니다. -> 프로그래머가 메모리의 수명을 자유롭게 결정하고 싶다. 크기 스택메모리는 특정 용도로 떼놓은 거라 크기가 작습니다. 차지할 크기를 컴파일 시에 결정하니까 크게 못 잡습니다. 그래서 엄청 큰 데이터를 처리해야 할 경우 스택 메모리에 못 넣죠. 예) 4K로 녹화해서 파일 크기가 2GB인 동영상 파일을 처리할 수 없음 -> 용량 제한 없이 메모리 사용하고 싶다 ■ 힙(Heap) 메모리의 장점 크기 컴파일러 및 CPU가 자동적으로 메모리 관리를 안 해주기 때문에 (unm.. 2020. 7. 15.

[ C ] 메모리 이해하기4 _스택(stack) 메모리란? 스택(stack) 메모리란? - 함수를 호출할 때 스택에 정확이 어떤게 어떤 순서로 들어가는지 알고 싶으면 함수 호출 규약에 따라 달라짐 어떤 컴파일러는 어떤 규격을 쓰는 매개변수 쓸때 어디부터 푸쉬한다든지 등 규약이 정해져 있으니깐 호출 받는 애와 주는 애에 관한 규약 2020. 7. 15.

[ C ] 메모리 이해하기3 _register 키워드란? register 변수의 제약 register 키워드란? register 변수의 제약 ■ register란? 프로그래머가 레지스터를 직접 사용하려면 어셈블리어로 코딩하면 됩니다. 물론 C언어도 가능하지만 레지스터 사용을 '요청'만 하기 때문에 실제로 그 명령이 레지스터로 갈 지, 스택 메모리로 갈 지는 컴파일러 마음입니다. 진짜 레지스터로 갔는지 확인하려면 어셈블러를 보면됩니다. 데이터를 레지스터에 저장한다고 할 때 register 키워드를 사용하면 됩니다. 이런 키워드를 저장 유형 지정자(storage-class specifier)라고 하는데 데이터를 어떻제 저장해야 하냐를 알려주는 키워드입니다. register 선언 방법은 아래와 같습니다. register ; int num; register size_t i; // .. 2020. 7. 14.

[ C ] 메모리 이해하기2_레지스터(Register)란? 필요한 이유 레지스터(Register)란? 레지스터가 필요한 이유 CPU 안에 있는 레지스터는 엄밀히 말하면 메모리가 아닙니다. 단지 휘발성으로 데이터를 저장하는 공간입니다. 그 휘발성 덕분에 프로그램을 메모리에 올렸다가 CPU에서 실행하면 굉장히 빨리 처리할 수 있습니다. 그런데 왜 굳이 레지스터를 CPU 안에서 동작하게 만들었을까요? 어떤 원리로 CPU 안에 있는 레지스터가 처리 속도가 빠르다고 할 수 있을까요? 먼저 이전 글을 잠시 복습해보면 CPU는 사람의 뇌, 메모리는 메모장이라고 했습니다. 여기서 하나만 생각해볼께요. 우리는 생각하는게 빠르나요? 적는게 빠르나요? 지금 누군가와 대화를 나누고 있다면, 듣는 동시에 머리 속으로 곱씹어 보는거랑 오고간 문장을 손으로 다 쓰는 것 중 당연히 뇌로 생각하는게 빠릅.. 2020. 7. 13.