Ссылка только на заголовок - PullRequest
5 голосов
/ 28 сентября 2011

Многие проекты C ++ (например, многие Boost библиотеки) «связаны только заголовками».

Возможно ли это и в простом C? Как поместить исходный код в заголовки? Есть ли сайты об этом?

Ответы [ 4 ]

11 голосов
/ 28 сентября 2011

Краткое содержание: Вы можете, но не должны.

Код C и C ++ предварительно обработан до его компиляции: все заголовки "вставляются" висходные файлы, которые включают их, рекурсивно.Если вы определите функцию в заголовке, и она будет включена в два файла C, вы получите две копии в каждом объектном файле ( Одно правило определения нарушение).

Вы можете создатьC-библиотеки «только для заголовков», если все ваши функции помечены как static, то есть не видны за пределами модуля перевода.Но это также означает, что вы получите копию всех статических функций в каждом модуле перевода, который включает файл заголовка.

В C ++ это немного отличается: встроенные функции не являются static, символы, испускаемыекомпилятор все еще виден компоновщику, но компоновщик может отбрасывать дубликаты, вместо того, чтобы сдавать («слабые» символы).

Нетрудно писать код C в заголовках, если он не основан на макросах (например,queue(3)).В C ++ основной причиной сохранения кода в заголовках являются шаблоны, что может привести к созданию экземпляра кода для различных параметров шаблона, что неприменимо к C.

4 голосов
/ 28 сентября 2011

Boost интенсивно использует шаблоны и метапрограммирование шаблонов, которые вы не можете эмулировать (все это легко) в C.

Но вы, конечно, можете обмануть, имея объявления и код в заголовках C, которые вы #includeно это не одно и то же.Я бы сказал «Когда в Риме ...» и запрограммируйте C согласно соглашениям C с библиотеками.

4 голосов
/ 28 сентября 2011

Вы не связываете заголовки.

В C ++ немного легче писать код, который уже лучше в заголовках, чем в отдельно скомпилированных модулях, потому что шаблоны требуют этого. 1

Но вы также можете использовать ключевое слово inline для функций, которые существуют как в C, так и в C ++. 2

// Won't cause redefinition link errors, because of 6.7.4/5
inline void foo(void) {
   // ...
}

[c99: 6.7.4/5:] Функция, объявленная со спецификатором функции inline, является встроенной функцией . Спецификатор функции может появляться более одного раза;поведение такое же, как если бы оно появилось только один раз. Создание функции как встроенной функции предполагает, что вызовы функции должны быть максимально быстрыми.Степень эффективности таких предложений определяется реализацией.

Однако вы немного застряли, когда дело доходит до объектов данных.


1 - Вроде. 2 - C99 точно.C89 / C90 я должен проверить.

3 голосов
/ 28 сентября 2011

Да, это вполне возможно.Объявите все функции в заголовках и все как static или просто используйте одну единицу компиляции (т.е. только один файл c) в ваших проектах.

В качестве личного анекдота я знаю немало физиков, которыенастаивайте на том, что этот метод является единственным верным способом программирования C. Это полезно, потому что это версия -fwhole-program для бедного человека, т.е. делает возможной оптимизацию, основанную на знании поведения функции.Это практично, потому что вам не нужно изучать использование флагов компоновщика.Это плохая идея, потому что вся ваша программа должна быть скомпилирована как единое целое и перекомпилирована с каждым незначительным изменением.

Лично я бы рекомендовал оставить ее или, по крайней мере, идти с static только для несколькихфункции.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...