«Все, что должен знать компилятор о printf / sprintf, это их прототипы, а не их семантика».
Это та часть, которая не соответствует действительности. Что касается стандарта, любой части реализации C "разрешено" знать о любой другой части и выпускать диагностические данные, которые могут быть полезны для пользователя. Встроенные функции компилятора не требуются стандартом, как и эта конкретная диагностика, но они, безусловно, не запрещены.
Обратите внимание, что (что касается стандарта) стандартная библиотека является особенной, это не просто старая связанная библиотека. Если конкретная реализация / компилятор даже предоставляет пользователю механизм для связи с другой версией стандартной библиотеки, стандарт определенно не требует, чтобы он «работал», когда эта альтернативная библиотека имеет семантику, отличную от той, что изложена в стандарт.
Таким образом, в этом смысле все в стандартной библиотеке является «встроенными». Это часть спецификации языка Си. Компиляторам разрешается действовать при условии, что они ведут себя так, как требует стандарт.
Конечно, если спецификатор формата не известен до времени выполнения, тогда компилятор не может выполнить статическую проверку varargs. Но когда это известно во время компиляции, компилятор может принять поведение printf
так же верно, как и поведение memcpy
или целочисленного сложения.