1. 이스케이프 시퀀스
MS Learn 정의 : 백슬래시(\) 뒤에 한 문자나 숫자 조합이 오는 문자 조합을 이스케이프 시퀀스라고 한다. 줄 바꿈 문자, 작은따옴표, 또는 문자 상수의 다른 특정 분자를 나타내려면 이스케이프 시퀀스를 사용해야 한다. 이스케이스 시퀀스는 단일 문자로 간주되므로 문자 상수로 유효하다.
시퀀스의미
| \n | 개행 |
| \t | 탭 |
| \r | 캐리지 리턴 (커서를 줄 맨 앞으로) |
| \0 | 널 문자 (문자열 종료 표시) |
| \\, \', \" | 백슬래시/따옴표 자체 |
| \a, \b, \f, \v | 벨, 백스페이스, 폼피드, 수직탭 (터미널마다 렌더링 다름) |
| \101, \x41 | 8진수/16진수 지정 |
| \uAC00 | 유니코드 코드포인트 |
MS전용 : 표에 없는 문자 앞에 백슬래시가 오는 경우 컴파일러는 정의되지 않은 문자를 문자 자체로 처리한다. 예를들어 \c는 c로 처리된다.
2.C언어 표준 입출력
- getchar(void)
인자: 없음
반환값: 입력 문자 하나. 에러가 발생하면 EOF(-1)을 반환한다.
설명: 표준입력장치(stdin)로부터 문자 한 글자를 읽어와서 반환한다. 만약 표준입력장치의 버퍼(메모리)가 비어 있다면 사용자로부터 입력을 받아 버퍼를 채운 다음, 그 중 첫 번쨀 입력된 문자를 반환하고, 그렇지 않고 채워져 있다면 별도의 사용자 입력 없이 버퍼에 저장된 문자 한개를 읽어와 반환한다.
- fgetc(FILE* stream)
인자: 읽어들일 스트림을 가리키는 파일 포인터
반환값: 읽은 문자 하나(int 반환), 스트림 끝이나 에러 시 EOF(-1) 반환
설명: 지정된 스트림에서 문자 하나를 읽는다. getchar()가 stdin 고정인 것과 달리 임의의 파일이나 표준 스트림 어디서든 읽을 수 있다. getchar()는 사실상 fgetc(stdin)과 동일하다.
- putchar(int c)
인자: 출력할 문자 상수.
반환값: 출력할 문자 하나. 에러가 발생하면 EOF(-1)을 반환한다.
설명: 표준출력장치(stdout)인 콘솔에 영문 한 글자를 출력한다.
- fputc(int c, FILE* stream)
인자: 출력할 문자, 그리고 출력 대상 스트림
반환값: 출력한 문자, 에러 시 EOF(-1)반환.
설명: 지정된 스트림에 문자 하나를 쓴다. putchar(c)는 사실상 fputc(c,stdout)과 동일하다.
- _getch(void) 함수
인자: 없음
반환값: 입력받은 문자 하나(int로 반환).
설명: 콘솔(키보드)에서 문자 하나를 버퍼링 없이 즉시 입력받는다. getchar()와 달리 Enter키를 누를 필요 없이, 키를 누르는 순간 바로 반환된다. 입력한 문자는 화면에 표시되지 않는다(무에코). 윈도우 전용 함수로 #include <conio.h>헤더가 필요하며 C표준 함수가 아니다.
- _getche(void) 함수
인자: 없음
반환값: 입력받은 문자 하나(int로 반환).
설명: _getch()와 동일하게 콘솔에서 문자 하나를 버퍼링 없이 즉시 입력받는다. 차이점은 입력한 문자가 화면에 그대로 표시(에코)된다는 것. 이름의 마지막 e가 echo를 의미한다. 똑같이 윈도우 전용 헤더가 필요하다.
- gets(char * str)
버퍼 크기 제한이 없어서 C11부터 사용 금지. 제거됨.
- gets_s(char* str, rsize_t n)
인자: 저장할 버퍼, 그리고 버퍼의 크기 n
반환값: 성공시 str, 실패시 NULL
설명: stdin에서 한 줄을 읽어 str에 저장하되, n-1개 문자까지만 읽어서 오버플로우를 방지한다. 개행문자를 만나면 그 자리에서 멈추고, 개행문자 자체는 버퍼에 저장하지 않는다. 만약 입력이 버퍼 크기를 초과하면 str[0]을 \0으로 만들고 실패 처리가 된다. 프로그램이 강제로 죽어버릴수도 있다.
- fgets(char* str, int n, FILE* stream)
인자: 저장할 버퍼, 버퍼 크기 n, 읽어들일 스트림
반환값: 성공 시 str, EOF나 에러시 NULL
설명: 지정된 스트림에서 한 줄 읽어 str에 저장한다 최대 n-1개 문자까지 읽고, 개행문자를 만나면 멈추되, gets_s와 달리 개행문자를 버퍼에 그대로 포함해서 저장한다. gets_s와 달리 버퍼 크기를 넘어서는 입력도 그냥 n-1까지만 읽고 자른다. 나머지는 스트림에 남아있게 된다.
- puts(const char* str)
인자: 출력할 문자열
반환값: 성공 시 음이 아닌 값, 실패시 EOF
설명: stdout에 문자열을 출력하고, 출력 후 자동으로 개행문자를 추가한다.
- fputs(const char* str, FILE* stream)
인자 : 출력할 문자열, 출력 대상 스트림
반환값: 성공시 음이 아닌 값, 실패시 EOF
설명: 지정된 스트림에 문자열을 출력한다. puts와 달리 자동 개행을 추가하지 않으며, 문자열에 개행이 필요하면 직접 넣어야 한다.
- printf(const char* format, ...)
인자: 포맷 문자열, 그리고 포맷에 대응하는 가변 인자들
반환값: 출력한 문자의 갯수(널 종단 제외). 에러시 음수
설명: stdout에 포맷 문자열에 지정된 형식으로 값을 출력한다.
- fprintf(FILE* stream, const char* format, ...)
인자: 출력 대상 스트림 포맷 문자열, 가변 인자.
반환값: 출력한 문자 개수, 에러 시 음수
설명: 지정된 스트림에 포맷된 문자열을 출력한다.
- sprintf
스트림이 아닌 메모리 버퍼에 포맷된 문자열을 저장한다. 버퍼 크기 제한을 받지 않아 오버플로우가 발생한다. 비권장
- sprintf_s(char* buffer, size_t sizeOfBuffer, const char* format, ...)
인자: 버퍼, 버퍼 크기, 포맷 문자열, 가변 인자
반환값: 저장된 문자 개수, 실패 시 음수
설명: sprinf의 안전 버젼으로 버퍼 크기를 명시하여 오버플로우를 방지한다.
- snprintf(char* buffer, size_t size, const char* format, ...)
인자: 버퍼, 버퍼 크기, 포맷 문자열, 가변 인자.
반환값: 버퍼가 충분했다면 필요했을 문자 개수(실제 쓰여진 개수가 아님).
설명: C99 표준의 안전한 버퍼 포맷 함수. sprintf_s와 유사하게 크기를 제한하지만, 이식성이 더 좋고(표준 C), 필요한 전체 크기를 반환값으로 알려주어 동적 버퍼 크기 계산에 활용할 수 있다.
- scanf(const char* format, ...)
인자: 포맷 문자열, 값을 저장할 변수들의 주소(포인터)
반환값: 성공적으로 읽어 할당한 인자의 개수, 매칭 실패나 스트림 끝이면 그보다 적은 값 또는 EOF
설명: stdin에서 포맷 문자열에 맞춰 값을 입력받는다. 문자 열을 읽을 때 공백문자를 구분자로 사용하기 때문에 공백 문자 뒤의 문자열은 버퍼에 남게 된다. 공백문자를 포함한 문자열을 입력받으려면 gets계열의 함수를 사용한다. 개행 문자를 버퍼에 남긴다.
- scanf_s(const char* format, ...)
인자: 포맷 문자열, 값을 저장할 변수들의 주소(포인터), 버퍼 크기를 인자로 함께 전달해야한다.
반환값: 성공적으로 읽어 할당한 인자의 개수, 매칭 실패나 스트림 끝이면 그보다 적은 값 또는 EOF
설명: scanf의 안전 버전으로, 문자열/문자 입력 시 버퍼 오버플로우를 방지하도록 크기 검사를 수행한다.
예시:
char name[32];
scanf_s("%s", name, (unsigned)sizeof(name));
- fscanf(FILE* stream, const char* format, ...)
인자: 읽어들일 스트림, 포맷 문자열, 저장할 변수 주소들
반환값: 성공적으로 읽어 할당한 인자 개수, 실패시 EOF
설명: 자정된 스트림(파일)에서 포맷에 맞춰 값을 읽어들인다.
- sscanf(const char* buffer, const char* format, ...)
인자: 파싱할 문자열 버퍼, 포맷 문자열, 저장할 변수 주소들.
반환갑시 성공적으로 읽어 할당한 인자 개수.
설명: 스트림이 아니라 이미 메모리에 있는 문자열에서 포맷에 맞춰 값을 추출한다.
- sscanf_s(const char* buffer, const char* format, ...)
인자: 파싱할 문자열 버퍼, 포맷 문자열, 저장할 변수 주소들(크기 인자 추가 필요)
반환값: 성공적으로 읽어 할당한 인자 개수.
설명: ssancf의 안전 버전으로, 메모리 문자열에서 파싱 시 버퍼 크기를 검사하여 오버플로우 방지.
3. 스트림(Stream)이란?
C에서 입출력은 전부 스트림이라는 추상화된 개념을 통해 이루어진다. C프로그램이 실행되면 OS가 자동으로 3개의 스트림을 미리 열어준다. 여기서 열어준다라는 표현은 윈도우 기준에선 윈도우 커널이 미리 콘솔창에서 입력 버퍼, 출력 버퍼 핸들을 만들고 새로 살당되는 프로세스에게 입력/출력 핸들을 할당해서 넘겨준다는 의미이다.
스트림용도
| stdin | 표준 입력 (보통 키보드) |
| stdout | 표준 출력 (보통 화면) |
| stderr | 표준 에러 출력 (보통 화면, 에러 전용) |
이 셋은 FILE* 타입이다. 즉 printf는 사실 stdout이라는 스트림에 쓰는 함수고, getchar는 stdin이라는 스트림에서 읽는 함수이다.
printf("Hi"); // 사실상 fprintf(stdout, "Hi")와 동일
getchar(); // 사실상 fgetc(stdin)와 동일
4.버퍼링(buffering)이란 무엇인가.
컴퓨터에서 화면 글자 하나 출력하거나, 키보드의 글자 하나를 받는 것도, 실제로는 OS에게 처리해달라고 요청하는 과정이 필요하다. 이 요청의 비용이 크기 때문에(속도가 느려지기 때문에), 매 요청을 OS에게 보내는 것이 아닌, 버퍼라는 임시 저장 공간에 모아두고 일정량 이상이 쌓이면 한번에 보내서 처리한다. 버퍼링에는 모드가 3가지가 있는데, 각각 언제 버퍼에 쌓인 데이터를 내보내는가(flush)의 기준으로 나뉜다.
- Unbufferd(버퍼 없음)
규칙: 데이터가 생기는 즉시, 버퍼에 모으지 않고 바로 출력/전송.
예시: stderr. 왜냐하면 에러 메세지는 프로그램이 갑자기 크래시나 죽어도 보이고 죽어야 하기 때문에 즉시 보여야 한다.
- Line-bufffered(줄 단위 버퍼링)
규칙: 데이터를 버퍼에 모아뒀다가, 개행문자를 만나거나 버퍼가 가득 차면 그때 한꺼번에 내보냄.
- Fully-buffered(완전 버퍼링)
예시: stdin, stdout
규칙: 개행문자와 상관없이, 버퍼가 완전히 가득 찰 때까지 계속 쌓아두기만 함, 꽉 차야 실제로 내보낸다.(또는 프로그램이 수동으로 fflush()호출하거나 종료할 때)
예시: 파일에 연결된 스트림. 파이프로 리다이렉트된 stdin/stdout
5.stdin은 왜 Enter를 눌러야 반응하는가.
stdin은 앞서 말했듯 콘솔에 연결되어 있을때, 줄 단위로 버퍼링 된다. 즉, 키보드로 아무리 타이핑해도 Enter(개행문자 '\n')를 누르기 전까지는 그 입력이 프로그램으로 전달 안되고 운영체제에 계속 쌓이게 된다. Enter를 누르는 순간 그 한 줄 전체가 프로그램으로 전달되고 그 다음부터 getchar()같은 함수가 한 글자씩 꺼내쓰는 것이다. Enter를 누를때까지 프로그램이 멈추는 Blocking이 이 버퍼링 방식 때문에 발생한다.
stdout도 비슷하게 버퍼링 되는데, printf로 뭔가를 출력해도 실제 그 글자가 찍히는 시점은 다음 중 하나이다. :
- 개행문자(\n)를 만났을 때
- 버퍼가 가득 찼을 때
- 프로그램이 정상 종료될 때
즉, 대부분의 경우라면 보이겠지만 상황에 따라 printf("HI")라고만 쓰고 개행문자를 안 넣으면 버퍼에 대기중이라 안 보일 수도 있다.
6.예외: _getch()는 버퍼링을 건너뛴다.
_getch()는 이 스트림 체계를 아예 우회해서 키보드 입력을 즉시 가져온다. 그래서 게임처럼 키 누르자마자 반응해야 하는 프로그램에선 getchar() 대신 _getch()를 사영한다.
'공부' 카테고리의 다른 글
| 우리는 왜 UTF-8을 써야 하는가 (0) | 2026.07.07 |
|---|---|
| 버블정렬 (0) | 2026.07.06 |
| C/C++ 연산자 우선순위 (0) | 2026.07.05 |
| 데이터 모델별 비트 차이 (0) | 2026.07.04 |
| 메모리 구조(프로세스 주소공간 전체 구조) (0) | 2026.07.04 |