Это "инлайн", без "статического" или "Экстерн" когда-нибудь полезны в C99?
когда я пытаюсь построить этот код
inline void f() {}
int main()
{
f();
}
С помощью командной строки
gcc -std=c99 -o a a.c
я получаю ошибку компоновщика (неопределенная ссылка на f). Ошибка исчезает, если я использую static inline или просто inline, или если я компиляции с -O (таким образом, функция фактически встроена).
такое поведение, по-видимому, определено в пункте 6.7.4 (6) стандарта C99:
если все объявления области действия файла для a функция в блоке перевода включает в себя
inlineописатель функции безextern, то определение в этой единице перевода является встроенным определением. Встроенное определение не предоставляет внешнего определения для функции и не запрещает внешнее определение в другой единице перевода. Встроенное определение предоставляет альтернативу внешнему определению, которое переводчик может использовать для реализации любого вызова функции в той же единице перевода. Это не определено использует ли вызов функции встроенное определение или внешнее определение.
если я все это правильно понимаю, блок компиляции с определенной функцией inline как в приведенном выше примере только собирает постоянно, если есть внешняя функция с тем же именем, и я никогда не знаю, если моя собственная функция или внешняя функция вызывается.
разве это поведение не совсем глупо? Это когда-нибудь полезно, чтобы определить функцию inline без static или extern в C99? Я что-то упустил?
резюме ответов
конечно, я что-то упустил, и поведение не глупо. :)
как объясняет Немо, идея состоит в том, чтобы поставить определение функции
inline void f() {}
в заголовочном файле и только декларация
extern inline void f();
в соответствующем .файл c. Только extern объявление запускает генерацию внешне видимый двоичный код. И действительно, нет никакой пользы inline в a .c файл -- это полезно только в заголовках.
как поясняет обоснование комитета C99, приведенное в ответе Джонатана,inline это все об оптимизации компилятора, которые требуют определения функции, чтобы быть видимым в месте вызова. Это может быть достигнуто только путем размещения определения в заголовке, и, конечно же, определение в заголовке не должно выдавать код каждый раз, когда его видят компилятор. Но поскольку компилятор не вынужден фактически встроить функцию, где-то должно существовать внешнее определение.
3 ответов:
на самом деле этот отличный ответ также отвечает на ваш вопрос, я думаю:
идея заключается в том, что" inline "можно использовать в заголовочном файле, а затем" extern inline " в a .файл c. "extern inline" - это то, как вы указываете компилятору, какой объектный файл должен содержать (внешне видимый) сгенерированный код.
[обновление, в разработке]
Я не думаю, что есть какая-либо польза для " inline "(без "static" или " extern") в .файл c. Но в заголовочном файле это имеет смысл, и для этого требуется соответствующее объявление "extern inline" в некоторых .C-файл для фактического создания автономного кода.
из самого стандарта (ISO / IEC 9899: 1999):
Приложение J. 2 Неопределенное Поведение
- ...
- функция с внешней связью объявляется с помощью
inlineописатель функции, но также не определен в той же единице трансляции (6.7.4).- ...
комитет C99 написал a обоснование, и он говорит:
функции 6.7.4 спецификаторы
новая функция C99: The
inlineключевое слово, адаптированное из C++, это
> Я получаю ошибку компоновщика (неопределенная ссылка наf)работает здесь: Linux x86-64, GCC 4.1.2. Может быть ошибка в вашем компиляторе; я не вижу ничего в процитированном абзаце из стандарта, который запрещает данную программу. Обратите внимание на использование если, а не iff.
встроенное определение обеспечивает альтернатива внешнему определению, который переводчик мая используется для реализации любого вызова функции в той же единице перевода.
Итак, если вы знаете поведение функции
fи вы хотите вызвать его в узком цикле, вы можете скопировать-вставить его определение в модуль, чтобы предотвратить вызовы функций;или, вы можете предоставить определение, которое для целей текущего модуля эквивалентно (но пропускает проверку ввода или любую оптимизацию, которую вы можете себе представить). Автор компилятора, однако, имеет возможность оптимизации для размера программы вместо этого.
Comments