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

warning: format specifies type — формат не совпал с типом

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

Предупреждение значит: спецификатор (%d, %f, %s…) в строке формата printf или scanf не подходит к типу переданного значения. gcc пишет так:

Текст
warning: format '%d' expects argument of type 'int', but argument 2 has type 'double' [-Wformat=]

clang (в том числе gcc в macOS) — так:

Текст
warning: format specifies type 'int' but the argument has type 'double' [-Wformat]

Смысл один: формат %d ждёт int, а передан double. Исправьте формат или значение.

Какой формат нужен

Типprintfscanf
int%d%d
unsigned int%u%u
long%ld%ld
long long%lld%lld
unsigned long long%llu%llu
size_t (результат sizeof, strlen)%zu%zu
double%f, %lf, %e, %g%lf
float%f%f
char%c%c
строка char[], char *%s%s
указатель%p с (void *)—

Частые случаи

Забыт & в scanf.

Текст
warning: format '%d' expects argument of type 'int *', but argument 2 has type 'int'

scanf нужен адрес: scanf("%d", &n). Без & программа почти наверняка упадёт.

strlen или sizeof с %d.

Текст
warning: format '%d' expects argument of type 'int', but argument 2 has type 'size_t' {aka 'long unsigned int'}

Результат strlen и sizeof — size_t. Его формат — %zu: printf("%zu\n", strlen(s));.

Дробное число с %d или целое с %f. printf("%d", 3.5) и printf("%f", 7) выводят мусор, а не 3 и 7.0: printf не переводит значения из одного типа в другой, он читает аргумент так, как велит формат. Нужно приведение — (int)x, (double)n — или другой формат.

long long с %d. Выведется только часть числа или мусор. Формат — %lld.

Число аргументов не совпало. printf("%d %d\n", a) — второго аргумента нет, gcc пишет format '%d' expects a matching 'int' argument. Лишние аргументы gcc тоже замечает: too many arguments for format.

Пример: всё верно

C
#include <stdio.h>
#include <string.h>

int main(void) {
    int n = 42;
    long long big = 3000000000LL;
    double x = 2.5;
    char s[] = "text";
    printf("%d %lld %.1f %s %zu %c\n", n, big, x, s, strlen(s), s[0]);
    return 0;
}
Вывод
42 3000000000 2.5 text 4 t

Почему это важно

printf и scanf не знают типов своих аргументов — только то, что написано в формате. Если формат не тот, поведение не определено: printf выводит мусор, а scanf записывает в память не то и не туда, иногда за пределы переменной. Поэтому предупреждения -Wformat — почти всегда настоящая ошибка. Они включаются ключом -Wall; собирайте с ним всегда.