C언어/C언어 심화 & 특수

[C11] gets() 대신 get_s()? fgets()? 무엇을 쓸까?

카루-R 2020. 3. 21. 10:03
반응형

결론: fgets() 쓰세요.

C11이 되면서 보안상 엄청난 결함을 가지고 있던 gets() 함수가 드디어 삭제되었습니다. 이제 최신 컴파일러에서는 gets()를 사용할 수 없습니다. 사용할 수는 있어도 보안 경고가 뜰 겁니다.

비주얼 스튜디오에서는 get_s()를 사용하라고 하는군요. 그런데, gets_s()는 표준이긴 하지만 optional이라 지원되지 않는 컴파일러도 꽤 있는 것으로 알고 있습니다. 그래서 대부분은 fgets()를 더 추천하죠.

두 함수의 원형은 이렇습니다.

char *gets_s( char *str, rsize_t n ); // C11 부터, 선택사항
char *fgets( char *restrict str, int count, FILE *restrict stream ) // C99 표준

두 함수의 차이점이라면 gets_s()는 stdin에서 입력을 받고, fgets()는 입력 스트림을 직접 정해야 한다는 것 입니다.

 

gets_s()

n == 0 이거나 n > RSIZE_MAX일때, str == NULL일때, 혹은 입력 받은 문자열이 버퍼보다 크면 프로그램이 자동으로 터집니다 (런타임 에러)

 

fgets()

count < 1이면 동작이 정의되지 않습니다. count == 1일때 널 문자가 입력될 때의 동작도 정의되지 않습니다.

gets_s()는 C11 표준, fgets()는 C99 표준(이전부터 있었지만, C99에서 개정됨)입니다. 호환성 면에선 C99의 fgets()가 더 좋습니다. _s() 함수들은 선택사항이라 gets_s()를 지원하지 않는 컴파일러도 많을 겁니다.

사용법은 이렇습니다.

#include <stdio.h>

int main(void) {
    char buf[100] = {""};

    printf("Enter anything: ");
    gets_s(buf, sizeof buf);
    printf("You've entered: %s\n\n", buf);

    for (int i = 0; i < 100; i++) buf[i] = '\0';

    printf("Now Enter something different: ");
    fgets(buf, sizeof buf, stdin);
    printf("You've entered: %s\n\n", buf);
}

간단합니다. 두 번째 매개변수에 sizeof + (배열 이름) 만 작성하시면 됩니다.

fgets는 늘 하던 대로 FILE* 스트림에 stdin만 적어주면 됩니다.

저라면 막강한 C++의 string 클래스를 fgets를 쓰겠습니다. 괜히 gets_s() 썼다가 다른 환경에서 컴파일 안 되면 곤란하니까..

반응형