В чем разница между статической встроенной функцией, встроенной внешней функцией и нормальной встроенной функцией?

В чем разница между static inline, extern inline и нормальной inline функцией?

Я видел несколько расплывчатых объяснений по этому поводу. Насколько я понял, static inline - это не просто функция inline, на которую следует ссылаться только в определенном файле, как обычно означает ключевое слово static. То же самое и с extern inline, я думаю, это не то же самое объяснение, что и с extern переменными. Будем признательны за любые ответы!


person Forever a noob    schedule 28.07.2014    source источник
comment
возможный дубликат: stackoverflow.com/questions/7762731/   -  person    schedule 28.07.2014
comment
все это встроенные функции. статическая встроенная функция - это статическая функция, extern inline - это функция, объявленная извне, обычная inline - это просто нормально.   -  person MAKZ    schedule 28.07.2014
comment
возможный дубликат: stackoverflow.com/questions/216510/extern-inline   -  person Hsi-Hung Shih    schedule 28.07.2014
comment
также прочтите stackoverflow.com/a/7767858/2204022   -  person MAKZ    schedule 28.07.2014
comment
Возможный дубликат extern inline   -  person o11c    schedule 08.07.2018


Ответы (1)


Определение функции с static inline определяет встроенную функцию с внутренней связью. Такая функция работает «как и ожидалось» из «обычных» свойств этих квалификаторов: static дает ей внутреннюю связь, а inline делает ее встроенной. Итак, эта функция является «локальной» для единицы перевода и встроена в нее.

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

Определение функции с extern inline определяет встроенную функцию с внешней связью, и в то же время это определение служит внешним определением для этой функции. Такую функцию можно вызвать из других единиц перевода.

Последние два абзаца означают, что у вас есть выбор: предоставить одно определение extern inline для встроенной функции с внешней связью или предоставить для нее два отдельных определения: одно inline и другое extern. В последнем случае, когда вы вызываете функцию, компилятор может выбрать любое из двух определений.

person AnT    schedule 28.07.2014
comment
Уточнение вашего последнего абзаца: для предоставления двух отдельных определений нет необходимости (и фактически не рекомендуется) предоставлять два функциональных тела. Вместо этого extern inline void f();, который выглядит (и является) объявлением, имеет эффект преобразования более раннего inline void f() { ..... } в внешнее определение вместо встроенного определения для этого модуля. (Ссылка C11 6.7.4 / 7). - person M.M; 29.06.2015
comment
Читая этот ответ, мне трудно понять точное значение внешнего определения и внутреннего определения. Где я могу узнать об этом больше? - person learnlearnlearn; 07.04.2019
comment
или предоставление двух отдельных определений inline int il_fun0(void) { return 0; } extern int il_fun0(void) { return 0; } приводит к ошибке компиляции C11: переопределение 'il_fun0' (с extern или без него). ` - person chux - Reinstate Monica; 09.12.2020
comment
@learnlearnlearn Встроенное определение используется для встраивания функций. Как обычно, внешнее определение используется для вызова функции. Ключевое слово inline - это просто подсказка для компилятора, поэтому вы не можете гарантировать, будет ли ваш вызов функции скомпилирован для встраивания или обычного вызова. В результате мы должны подготовить два определения для одной и той же встроенной функции. Каждая единица перевода, вызывающая встроенную функцию, должна иметь собственное встроенное определение для обработки встраивания. Более того, только одна единица трансляции должна иметь внешнее определение для обработки обычного вызова. - person jinbeom hong; 26.01.2021
comment
@learnlearnlearn Например, когда вы отключите опцию оптимизации вашего компилятора, встроенный вызов функции будет скомпилирован в обычный вызов функции. В этом случае все обычные вызовы относятся к одному и тому же внешнему определению. В то время как, когда вы включаете опцию оптимизации, встроенный вызов функции будет скомпилирован для встраивания. В этом случае встраивание достигается за счет собственного встроенного определения каждой единицы перевода. Поэтому мы помещаем inline void func(void) {} в файл заголовка для встраивания и помещаем extern inline void func(void); в исходный файл (отдельная единица перевода) для обычного вызова. - person jinbeom hong; 26.01.2021