В случае библиотеки импорта для DLL, файл .lib не вообще содержит какой-либо действительный код. В основном он содержит только список функций в связанной DLL - достаточно, чтобы компоновщик вставил ссылку на эту DLL во что-то связанное с библиотекой, но не более того.
Файл .exp - это файл экспорта - в основном примерно такой же, как файл .lib. Он используется (по крайней мере, в основном), когда у вас есть круговая зависимость. Например, предположим, что у вас есть DLL, которая действует как плагин для исполняемого файла. Исполняемый файл предоставляет некоторые экспортированные функции для использования библиотеками подключаемых модулей, но также должен иметь возможность вызывать некоторые функции в подключаемых модулях (например, загружать и инициализировать подключаемый модуль).
DLL не будет связываться, пока исполняемый файл не будет создан для предоставления файла .lib - но исполняемый файл не будет связываться, пока библиотека не будет создана для предоставления файла .lib. Чтобы разорвать зависимость, вы запускаете компоновщик для исполняемого файла, который завершается неудачно (поскольку он не может найти файл .lib для DLL), но будет создавать файл .exp. Затем вы связываете DLL с файлом .exp для исполняемого файла. Затем вы можете повторно запустить ссылку для создания исполняемого файла, используя .lib-файл для DLL.