Так как на мой вкус все ответы, даже принятые, ошибочны в главном аспекте inline
и, в частности, в том, что это означает для использования в макросах, я пробую другой.
inline
ключевое слово определяет, приведет ли определение функции (не объявление) к генерации функции в текущем модуле компиляции.В основном это 3 случая:
- Если вы просто зададите «простое» определение, то должна быть сгенерирована функция и вставлен внешний символ для этой функции.
- Для определения
inline
функция может быть сгенерирована , и если это так, то может вставлять или не вставлять внешний символ в объект. - Для определения
static
функция может быть сгенерировано (обычно, если оно используется), но имя никогда не будет внешним символом.
Во-первых, если два модуля компиляции определяют одну и ту же функцию, будет ошибкапри соединении двух объектных файлов в одном исполняемом файле.
В последующем, если два модуля компиляции определяют одну и ту же функцию, оба объектных файла будут содержать копии функции, которые не будут объединены, когда они связаны.
Что касается макросов, представленных в вопросе, это имеет важное функциональное отличие.Первый, inline
, можно развернуть в любом месте, особенно в заголовочном файле, не вызывая конфликтов.Второй можно использовать только в файле .c, и, кроме того, два таких .c не должны делать это, если они попадают в один и тот же исполняемый файл.
Edit: wrtна комментарий Чарльза.Функции inline
также могут быть внешними символами.Правила для этого немного сложны, см. Соответствующий параграф 6.7.4 из C99 ниже.В основном, есть три случая, которые будут работать, если у вас есть несколько единиц перевода, которые будут связаны друг с другом
- объявить и определить функцию
extern inline
в файле .h и объявить этоснова просто inline
без extern
в одном файле .c. - объявите и определите функцию
inline
в файле .h и повторно объявите ее без inline
в одном файле .c.Фактически это похоже на создание шаблонных функций в C ++. - объявляет и определяет функцию
inline
в файле .h и повторно объявляет ее extern inline
только в одном файле .c.
До версии 4.3 у gcc была другая модель для этого типа реализации inline
функций, несовместимая с этой нормативной. См. Также эту страницу для прочтения этой темы.
Любая функция с внутренней связью может быть встроенной функцией.Для функции с внешним связыванием применяются следующие ограничения: Если функция объявлена со встроенным спецификатором функции, то она также должна быть определена в той же единице перевода.Если все объявления области действия файла для функции в модуле перевода включают спецификатор встроенной функции без extern, то определение в этом модуле перевода является встроенным определением.Встроенное определение не предоставляет внешнего определения для функции и не запрещает внешнее определение в другой единице перевода.Встроенное определение предоставляет альтернативу внешнему определению, которое переводчик может использовать для реализации любого вызова функции в том же модуле перевода.Не определено, использует ли вызов функции встроенное определение или внешнее определение.