Глиф Учебники

Ошибка C4996 в Visual Studio: scanf may be unsafe

Справочник · C++ · 1 минута чтения

Visual Studio не собирает программу и пишет:

Текст
error C4996: 'scanf': This function or variable may be unsafe. Consider using scanf_s instead.
To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.

Компилятор Microsoft считает «небезопасными» некоторые функции языка C — scanf, strcpy, strcat, fopen, freopen и другие: при неосторожном использовании они могут записать данные за границу массива. Сообщение об этом — предупреждение C4996, но в новых проектах Visual Studio включены проверки SDL (дополнительные проверки безопасности кода, ключ /sdl), и с ними предупреждение становится ошибкой.

Решение: первая строка файла

Добавьте в самое начало файла, до всех #include:

C++
#define _CRT_SECURE_NO_WARNINGS
#include <cstdio>

int main() {
    int a, b;
    scanf("%d %d", &a, &b);
    printf("%d\n", a + b);
    return 0;
}
Ввод
2 3
Вывод
5

Строка должна стоять именно перед #include: если поставить её ниже, заголовки уже будут прочитаны, и она не подействует. Другие компиляторы (g++, clang) эту строку просто не замечают, поэтому программа с ней собирается везде.

Другой способ — для всего проекта сразу: в свойствах проекта, раздел «C/C++» → «Препроцессор», добавьте _CRT_SECURE_NO_WARNINGS в «Определения препроцессора» через точку с запятой от уже записанных там значений.

Почему не scanf_s

Visual Studio предлагает заменить scanf на scanf_s. Но scanf_s в C++ — функция Microsoft: g++ и большинство проверяющих систем олимпиад её не знают, и решение с ней получит ошибку компиляции. Если программа должна собираться не только в Visual Studio, оставьте scanf и добавьте _CRT_SECURE_NO_WARNINGS.

У scanf_s к тому же другие правила для строк: после адреса массива char нужен его размер. Код, переписанный механической заменой scanf на scanf_s, может работать неверно.

А можно без scanf

Можно: в C++ есть cin и cout, и предупреждения C4996 с ними не бывает. По скорости они почти не уступают scanf, если включить быстрый режим — см. Быстрый ввод-вывод. Строки C (char[] и strcpy) обычно заменяют на string, а файлы — на ifstream и ofstream (см. Ввод из файла и вывод в файл).

Отключать проверки SDL целиком (свойства проекта, «C/C++» → «Общие») не нужно: они ловят и другие настоящие ошибки. Достаточно _CRT_SECURE_NO_WARNINGS.