warning: format specifies type — формат не совпал с типом
Предупреждение значит: спецификатор (%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. Исправьте формат или значение.
Какой формат нужен
| Тип | printf | scanf |
|---|---|---|
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.
Пример: всё верно
#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; собирайте с ним всегда.