Импорт файлов заголовков C вопрос о том, что включено

Я немного запутался в файлах заголовков.

Насколько я понимаю заголовочные файлы в C, такие как #include <windows.h>, включаются только необходимые части в зависимости от того, какие функции используются в программе. Например, если бы в исходном коде была реализована только функция MessageBox(), то из заголовочного файла были бы включены только необходимые части.

Однако я наткнулся на WindowsHModular на GitHub здесь, который утверждает, что позволяет программисту включать только то, что требуется, поскольку автор GitHub разделил Windows.h на различные модули.

Это кажется довольно противоречивым, поэтому я надеялся, что кто-нибудь поможет мне разобраться в моих фактах.

@pmacfarlane Что, если бы я включил другой заголовок, например <stdio.h>, но никогда не использовал в исходном файле никаких функций, таких как printf()?

securityauditor 20.02.2023 23:41

Это должен быть повторяющийся вопрос... Файлы заголовков объявляют токены и прототипы функций, поэтому компилятор знает определенные значения и может сообщить о неправильном использовании. Последующее связывание — это когда код извлекается из библиотек и «связывается» вместе с вашей программой. C не импортирует код из заголовочных файлов.

Fe2O3 20.02.2023 23:46

Включение заголовочного файла почти равносильно замене директивы #include полным текстом включаемого файла. см. cprogramming.com/reference/preprocessor/include.html или en.wikibooks.org/wiki/C_Programming/…

Bodo 20.02.2023 23:47

@ Fe2O3 Что такое токен?

securityauditor 20.02.2023 23:48
MessageBox() не реализован в заголовочном файле. Заголовочный файл содержит только объявление, поэтому никакого кода не генерируется. Компоновщик должен заполнить таблицы импорта для каждого используемого импорта.
IInspectable 20.02.2023 23:49

«Что такое токен?» демонстрирует потребность в том, чтобы вы сели за хорошую книгу по языку и начали учиться самостоятельно.

Fe2O3 20.02.2023 23:50

Токены @Fe2O3 не были описаны ни в Head First C, ни во 2-м издании языка программирования C... Судя по всему, токен может быть любым из следующих:  ключевое слово  идентификатор  константа  строковый литерал  оператор  пунктуатор

securityauditor 20.02.2023 23:52

@IInspectable У вас есть ссылка на краткое объяснение того, как работают таблицы импорта для импорта?

securityauditor 20.02.2023 23:52

Fe2O3 20.02.2023 23:57

securityauditor 20.02.2023 23:59
Руководство для начинающих по веб-разработке на React.js
Руководство для начинающих по веб-разработке на React.js
Веб-разработка - это захватывающая и постоянно меняющаяся область, которая постоянно развивается благодаря новым технологиям и тенденциям. Одним из...
Разница между Angular и React
Разница между Angular и React
React и AngularJS - это два самых популярных фреймворка для веб-разработки. Оба фреймворка имеют свои уникальные особенности и преимущества, которые...
Инструменты для веб-скрапинга с открытым исходным кодом: Python Developer Toolkit
Инструменты для веб-скрапинга с открытым исходным кодом: Python Developer Toolkit
Веб-скрейпинг, как мы все знаем, это дисциплина, которая развивается с течением времени. Появляются все более сложные средства борьбы с ботами, а...
Калькулятор CGPA 12 для семестра
Калькулятор CGPA 12 для семестра
Чтобы запустить этот код и рассчитать CGPA, необходимо сохранить код как HTML-файл, а затем открыть его в веб-браузере. Для этого выполните следующие...
ONLBest Online HTML CSS JAVASCRIPT Training In INDIA 2023
ONLBest Online HTML CSS JAVASCRIPT Training In INDIA 2023
О тренинге HTML JavaScript :HTML (язык гипертекстовой разметки) и CSS (каскадные таблицы стилей) - две основные технологии для создания веб-страниц....
Как собрать/развернуть часть вашего приложения Angular
Как собрать/развернуть часть вашего приложения Angular
Вам когда-нибудь требовалось собрать/развернуть только часть вашего приложения Angular или, возможно, скрыть некоторые маршруты в определенных средах?
0
11
69
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Нет,

Если вы включаете файл строки

#include <file.h> // or "file.h"

Заменяется содержанием file.h

Пример: https://godbolt.org/z/a3WEP6hdP

Заголовочные файлы не являются библиотеками или объектными файлами. При компоновке компоновщик слинкует только используемую функцию (точнее все функции из используемых сегментов).

Но был бы мой окончательный размер исполняемого файла меньше, если бы я использовал WindowsHModular? Конечно, включая <windows.h> со всеми его сотни, а может быть, тысячи строк раздуют исполняемый?

Правильный файл .h не определяет никаких данных или функций. Он должен содержать только определения макросов, объявления типов данных, объявления внешних объектов и прототипы функций. .h файл может состоять из сотен тысяч строк, но он ничего не добавит к исполняемому файлу.

Итак, вы говорите, что даже если #include <file.h> помещает все из file.h в мой файл test.c, компоновщик удалит ненужные строки, добавленные file.h в test.c?

securityauditor 21.02.2023 00:15

Эти строки не добавляют никакого кода в ваш исполняемый файл.

0___________ 21.02.2023 00:26

Вы сказали, что #include <windows.h>, который я использовал в качестве примера, будет заменен тысячами строк из файла windows.h, верно? Конечно, это увеличит размер исполняемого файла?

securityauditor 21.02.2023 00:29

@securityauditor «конечно» не будет.

0___________ 21.02.2023 00:30

@securityauditor: ничего не добавляет к вашему исполняемому файлу. Размер исполняемого файла определяется компоновщиком, который будет включать только тот код, который фактически используется в вашем приложении. Заголовочный файл может определять тысячи функций, но если ваш код на самом деле не вызывает эти функции, они не будут связаны с вашим приложением.

Ken White 21.02.2023 02:10

@KenWhite на самом деле это не на 100% правильно. ld можно отбросить на уровне раздела, а не на уровне функции. Так что если функции в библиотеках и объектных файлах разместить в своих разделах, то будет работать так, как вы описываете. Если нет, то достаточно одной функции из раздела, чтобы использовать ее для всего размещения раздела. Поэтому при компиляции всегда размещайте функции в своих разделах.

0___________ 21.02.2023 11:05

«Разделы» не являются частью спецификации языка C. Это ld уступка откровению о том, что попытка масштабирования до бесконечности («каждый символ в открытом наборе по умолчанию общедоступен») не масштабируется. Комментарий @KenWhite точен с точки зрения клиента, использующего компоновщик, построенный на разумных принципах (например, MSVC link.exe).

IInspectable 21.02.2023 17:28
Мое понимание файлов заголовков в C, таких как #include <windows.h>, заключается в том, что включаются только необходимые части в зависимости от того, какие функции используются в программе.

Я думаю, это зависит от того, что вы подразумеваете под «включено». Возможно, вы путаете включение заголовка со связыванием, которое является совершенно отдельным этапом позже в процессе компиляции.

На высоком уровне #include директивы просты. Они предписывают компилятору читать исходный код из другого файла, как если бы он появился вместо директивы. Вот и все. Нет врожденного выбора и выбора разных частей. Подумайте: как компилятор узнает, какие фрагменты вам нужны, прежде чем он обработает остальную часть исходного файла?

Принципиальной разницы между файлами заголовков и «обычными» исходными файлами нет, но стало общепринятым и очень строгим обычаем помещать в заголовки только определенные виды кода, в первую очередь:

  • объявления функций
  • определения макросов
  • struct, union и enum определения типов
  • объявления внешних переменных
  • typedef определения

В основном это вещи, которые должны быть одинаково объявлены в нескольких независимых исходных файлах, и размещение их в файлах заголовков облегчает это и значительно упрощает обслуживание, когда один из них необходимо изменить.

Это также вещи, которые не влияют на программу, если они не используются. Например, результирующая программа не будет больше или сложнее, если источник объявляет функции, которые он никогда не вызывает, будь то с помощью #includeзаголовка или путем их объявления напрямую.

Тем не менее, я наткнулся на WindowsHModular на GitHub здесь, который утверждает, что позволяет программисту включать только то, что требуется, поскольку автор GitHub разделил Windows.h на различные модули.

Проблема с Windows.h в том, что он огромный и сложный. Хотя это не имеет значения для скомпилированных программ, это требует от компилятора значительных усилий. Цель разделения Windows.h на отдельные модули — сократить время ЦП и память, необходимые для компиляции программ, позволяя вам опустить кучу объявлений, которые вам все равно не нужны.

На данный момент вам, вероятно, лучше игнорировать WindowsHModular.

Но был бы мой окончательный размер исполняемого файла меньше, если бы я использовал WindowsHModular? Конечно, включение <windows.h> со всеми его сотнями, а может быть, тысячами строк приведет к раздуванию исполняемого файла?

securityauditor 21.02.2023 00:23

Нет, @securityauditor, как я уже писал. Более того, десятки тысяч строк Windows.h и других заголовков, которые он сам включает, ни на йоту не увеличивают размер исполняемого файла. Внутри нет ничего исполняемого, только объявления. Объявления указывают компилятору, как интерпретировать другой код, но они не имеют собственного поведения во время выполнения.

John Bollinger 21.02.2023 00:28

Объявления @securityauditor не генерируют никакого кода. Они просто вводят символы для компилятора. И определения удаляются компоновщиком, если они не используются. Поскольку компоновщик MSVC по умолчанию использует частные символы, есть много возможностей для очистки.

IInspectable 21.02.2023 00:29
it does make the compiler expend a fair amount of effort. сейчас это кого-то волнует?
0___________ 21.02.2023 00:32

Удивительно, @0___________. Ясно, что автор WindowsHModular когда-то делал, и, возможно, делает до сих пор, так как проект обновлялся в течение последнего года.

John Bollinger 21.02.2023 00:34

@JohnBollinger есть zmilions бесполезных живых проектов

0___________ 21.02.2023 00:35

Да, @0___________, но вы не спросили, было ли это полезно. Вы спросили, волнует ли это кого-нибудь. Вы заметите, что я рекомендовал ОП игнорировать WindowsHModular. Мое мнение об усилиях компилятора заключалось в том, чтобы объяснить мотивацию такого проекта, а не приписывать ему полезность.

John Bollinger 21.02.2023 00:39

@JohnBollinger Я хотел показать OP, что не имеет значения, сколько строк в вашем файле .h.

0___________ 21.02.2023 00:53

@securityauditor Если вам небезразлично время компиляции, вы можете использовать символы препроцессора, чтобы ограничить поверхность API, которую компилятору придется обрабатывать (инструкции см. в разделе Более быстрые сборки с меньшими файлами заголовков).

IInspectable 21.02.2023 00:56

Другие вопросы по теме