전체 글 (157) 썸네일형 리스트형 [C언어] 버퍼(Buffer), 입출력버퍼 비우기(fflush) 버퍼 (Buffer) 지금까지 써왔던 scanf와 printf 등 stdio.h 에서 제공하는 표준 입출력함수들을 사용할 경우 해당 데이터들은 운영체제가 제공하는 '메모리 버퍼'를 중간에 통과하게 된다. 키보드로 데이터를 입력할 때 한 글자 한 글자 입력할 때마다 즉시 프로그램으로 전달되는 것이 아니라 일단 입력버퍼에 저장된 다음에 프로그램으로 저장되는 것이다. 이때 입력버퍼에서 프로그램으로 데이터가 전달되는 시점은 엔터 키가 눌리는 시점이다. 이 일련의 작업을 버퍼링(Buffering)이라고 한다. 그렇다면 버퍼링을 하는 이유는 무엇일까? 데이터를 하나씩 전달하는 것보다 여러 개의 데이터를 한 번에 전달하는 것이 빠르고 효율적이기 때문이다. 출력버퍼 비우기 출력버퍼가 비워진다는 것은 데이터가 메모리버퍼.. [C언어] 파일 입출력 함수 (fputc, fputs, fgetc, fgets, putchar, getchar, puts, gets) 문자 입출력 함수 (putchar, getchar) putchar 함수와 getchar 함수의 경우 문자를 입출력하는 함수이다. 함수의 반환형과 요구하는 매개변수의 자료형은 아래와 같다. int getchar(void); int putchar(int c); putchar 의 인자로 출력할 문자를 전달해 주면 된다. 따라서 입출력함수는 아래 코드처럼 사용이 가능하다. #include int main() { int ch; ch = getchar(); putchar(ch); return 0; } 문자열 입출력 함수 (puts, gets) 문자열 입출력 함수는 문자 하나만이 아니라 문자열 자체를 입출력할 수 있다. 함수의 반환형과 요구하는 매개변수의 자료형은 아래와 같다. char* gets(char* s); .. [C언어] 스트림(Stream), EOF 스트림 (Stream) 쉽게 말해서 스트림이란 데이터의 이동경로를 의미한다. 데이터는 어디서 와 어디로 가는가? 가장 일반적으로 떠올릴 수 있는 대답은 키보드로 입력받은 데이터가 프로그램으로 흘러들어 가거나 반대로 프로그램에서 데이터를 모니터로 출력하는 경우일 것이다. 그러나 마우스, 프린터, 화상 카메라, 스캐너, 파일 등도 데이터 입력 대상이 될 수 있고 스피커, 파일 등도 출력의 대상이 될 수 있다. 이렇게 데이터 입출력 대상의 범위는 매우 넓고 포괄적인 의미가 있다. 그런데 모니터로 문자열을 어떻게 출력할 수 있는 걸까? 정확히 말해서 printf 함수 호출 시 어떤 과정을 거쳐서 문자열이 출력되는 것일까? 운영체제에서는 데이터를 외부로 출력하거나 외부에서 입력받을 수 있는 소프트웨어적인 가상의 .. [C언어] static 변수, register 변수 static 변수 지역변수에 static 선언을 추가하는 것으로 우리는 새로운 특성을 가진 변수를 만들 수 있다. static 변수는 선언된 함수 내에서만 접근 가능한 지역변수의 특성도 갖고 있고 딱 1회 초기화되고 프로그램 종료 시까지 메모리 공간에 존재한다는 전역변수의 특성도 갖고 있다. #include void func(int a) { static int num = 0; num+=a; printf("static : %d\n", num); } int main () { func(5); func(5); func(5); func(5); func(5); return 0; } 따라서 위 코드에서 num의 값이 함수가 호출될 때마다 5씩 증가하는 것을 확인할 수 있다. 이때 선언부는 최초 1회밖에 적용되지 않기.. [C언어] 상수형 포인터 (Const Pointer) 상수형 포인터 포인터를 상수로 선언하는 것도 가능하다. 이 때 주의할 점이 있는데 const 선언의 위치에 따라 의미가 달라진다는 점이다. const int * ptr = # 예를 들어 위 코드처럼 선언했을 경우 포인터변수를 사용하여 변수에 접근하는 것은 허용되나 포인터변수를 역참조하여 변수를 수정하는 것은 불가능하다는 의미이다. 따라서 아래 코드처럼 사용하는 것이 불가능하다. int num = 10; const int * ptr = # *ptr = 20; 그러나 포인터변수가 가리키고 있는 num까지 상수화된 것은 아니기때문에 아래 코드처럼 num의 값을 직접적으로 변경하는 것은 가능하다. int num = 10; const int * ptr = # num = 20; const 선언.. [C언어] scanf 호출 시 &연산자를 사용하는 이유 &연산자의 역할 scanf 함수는 값을 입력받아서 변수에 전달하는 역할을 한다. 해당 역할을 수행하기 위해서는 변수가 어디 저장되어 있는지 알아야 할 것이다. 따라서 &연산자를 통해 변수의 주소를 scanf 함수에 전달해주어야 하는 것이다. 그런데 문자열을 저장할 때에는 & 연산자를 필요로 하지 않는다. 이전 포스팅에서도 다루었듯이 문자열의 자료형은 char*형이다. 따라서 그 자체로 이미 주소값을 나타내고 있기 때문에 굳이 &연산자를 붙여주지 않아도 되는 것이다. 아니, &연산자를 붙이게 되면 틀린 문법이 되어버린다. [C언어] 포인터 반환 함수 포인터 반환 함수 포인터 반환 함수를 선언하는 방법은 반환값의 자료형과 함수 이름 사이에 *을 붙여주면 된다. 그러나 아래 코드처럼 작성할 경우 제대로 사용이 불가능할 것이다. int *Num() { int num = 5; return # } 위 코드처럼 사용하게 되면 지역변수인 num은 Num함수의 호출이 종료되면 사용이 끝났다고 판단되어서 프로그램 실행 중에 값이 손상될 수 있기 때문이다. 따라서 올바른 포인터 반환 함수의 사용법은 아래와 같다. int *Num() { int *ptr = malloc(sizeof(int)); *ptr = 5; return ptr; } 동적할당으로 메모리를 할당해주면 함수가 끝났을 때 ptr을 역참조 할 수는 없지만 free 함수로 메모리를 해제하기 전까지 메모.. [C언어] Call By Reference Call_By_Reference Call by value 함수와 Call by reference 함수를 구분하는 기준은 함수의 호출 방식이다. Call by value 함수는 인자로 변수를 받아오고 Call by reference 함수는 인자로 주소값을 받아온다. 아주 간단한 차이지만 이 둘의 차이는 극명하다. 인자로 변수를 받아오면 변수를 그대로 사용하는 것이 아니라 변수를 복제하여 함수에 전달하게 되는 것이다. 그러니 함수에서 변수를 변형시키려고 아무리 노력해도 복제본만 수정될 뿐인 것이다. 그래서 우리는 함수에 주소값을 전달하는 것으로 함수 안에서도 변수에 간접적으로 접근할 수 있게 만들 수 있다. Call By Value 방식으로 변수의 값을 증가시키려고 해보겠다. #include void fun.. 이전 1 ··· 8 9 10 11 12 13 14 ··· 20 다음