Компилятор не знает о динамическом линковании, он просто знает, что функция существует через свой прототип. Компоновщику нужны файлы lib для разрешения символа. Библиотека DLL для DLL содержит дополнительную информацию, например, о том, в какой библиотеке DLL находятся функции и как они экспортируются (по имени, по порядковому номеру и т. Д.). Файлы lib для DLL содержат гораздо меньше информации, чем файлы lib, которые содержат полный объектный код - libcmmt .lib в моей системе - 19,2 МБ, но msvcrt.lib - только 2,6 МБ.
Обратите внимание, что этой модели компиляции / компоновки уже почти 40 лет, и она предшествует динамической компоновке на большинстве платформ. Если бы он был разработан сегодня, динамическое связывание было бы первоклассным гражданином (например, в .NET каждая сборка имеет богатые метаданные, точно описывающие то, что она экспортирует, поэтому вам не нужны отдельные заголовки и библиотеки.)