Ответ 1
Строка формата не сообщает компилятору выполнить трансляцию в unsigned long long
, она просто сообщает printf
, что она получит unsigned long long
. Если вы передадите что-то, что не unsigned long long
(которое off_t
может и не быть), тогда printf
просто неправильно интерпретирует его с неожиданными результатами.
Причиной этого является то, что компилятор не должен ничего знать о строках формата. Хороший компилятор даст вам предупреждение, если вы напишете printf("%d", 3.0)
, но что может сделать компилятор, если вы пишете printf(s, 3.0)
, причем s
является строкой, определяемой динамически во время выполнения?
Отредактировано для добавления: Как указывает Кит Томпсон в комментариях ниже, есть много мест, где компилятор может выполнить такое неявное преобразование. printf
является довольно исключительным, будучи одним из случаев, когда он не может. Но если вы объявите функцию для принятия unsigned long long
, тогда компилятор выполнит преобразование:
#include <stdio.h>
#include <sys/types.h>
int print_llu(unsigned long long ull)
{
return printf("%llu\n", ull); // O.K.; already converted
}
int main()
{
off_t a;
printf("%llu\n", a); // WRONG! Undefined behavior!
printf("%llu\n", (unsigned long long) a); // O.K.; explicit conversion
print_llu((unsigned long long) a); // O.K.; explicit conversion
print_llu(a); // O.K.; implicit conversion
return 0;
}
Причиной этого является то, что printf
объявляется как int printf(const char *format, ...)
, где ...
представляет собой "вариационную" или "переменную аргументы", сообщающую компилятору, что он может принимать любое число и типы аргументов после format
. (Очевидно, что printf
не может принимать любые числа и типы аргументов: он может принимать только число и типы, о которых вы говорите, используя format
. Но компилятор ничего об этом не знает, он оставил программист для его обработки.)
Даже с ...
компилятор выполняет некоторые неявные преобразования, такие как продвижение char
в int
и float
в double
. Но эти преобразования не относятся к printf
, и они не зависят от строки формата и не могут зависеть.