У меня есть следующая структура:

Test.h :

extern BOOL some_variable;

inline BOOL get_some_variable()
{
    return some_variable;
}

Test.c

BOOL some_variable = 10;
// some functions that change 'some_variable'.

Main.c

int main()
{
    while(1) {
        if (get_some_variable()) { // do something }
    }
}

У меня вопрос, будет ли это работать должным образом. Под этим я подразумеваю, что вызов в основном будет заменен на some_variable? Или это создаст копии some_variable или что-то в этом роде? Нужно ли где-то объявить встроенную функцию как extern?

Я знаю, что могу просто проверять some_variable в main.c без необходимости в функции, но этот способ мне кажется более элегантным. Или есть лучший способ вернуть переменную из другого исходного файла без вызова функции. Я хочу, чтобы это уменьшило количество операций, необходимых для получения some_variable, потому что это для микроконтроллера.

c gcc
1
user1806687 27 Ноя 2016 в 18:40

2 ответа

Лучший ответ

Я согласен с выводом @JonathanLeffler о том, что форма определения встроенной функции, которую вы представляете, требует внешнего определения где-то в функции get_some_variable(), которое не предоставляется вашим test.h. Однако может оказаться, что ваш компилятор по-прежнему успешно строит вашу программу, поскольку он вполне может выбрать везде, чтобы использовать предоставленную встроенную функцию вместо ложно обещанной внешней.

Тем не менее то, что вы делаете, кажется немного глупым. Весь смысл встроенного определения функции с внешней связью заключается в предоставлении дополнительной локальной альтернативы внешней функции. Если вы хотите, чтобы встроенная функция использовалась всегда, было бы уместно объявить ее static в test.h:

extern BOOL some_variable;

static inline BOOL get_some_variable()
{
    return some_variable;
}

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

Или, с третьей стороны, в этом конкретном случае вы можете рассмотреть возможность прямого доступа к переменной, что в любом случае можно сделать из каждой единицы перевода. Если вы хотите инкапсулировать some_variable и ограничить доступ к нему, вам нужен другой подход.

2
John Bollinger 27 Ноя 2016 в 16:21

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

6.7.4 Спецификаторы функций

¶7 Любая функция с внутренней связью может быть встроенной функцией. Для функции с внешним связи, применяются следующие ограничения: Если функция объявлена со встроенным спецификатор функции, то он также должен быть определен в той же единице перевода. Если все объявления области действия файла для функции в блоке перевода включают встроенную функцию спецификатор без extern, тогда определение в этой единице перевода является встроенным определение. Встроенное определение не предоставляет внешнего определения функции, и не запрещает внешнее определение в другой единице перевода. Встроенное определение предоставляет альтернативу внешнему определению, которое переводчик может использовать для реализации любой вызов функции в той же единице перевода. Не указано, был ли вызов функция использует встроенное определение или внешнее определение. 140)

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

Пока main.c имеет #include <test.h>, вы, скорее всего, получите тело функции, которое используется встроенным - без накладных расходов на вызов функции - в программе main().

В целом, вероятно, безопаснее всего использовать static inline везде (как John Bollinger suggests ). См. Также Is inline без {{X2 }} или extern когда-либо было полезно в C, и вполне могут возникнуть другие соответствующие вопросы по SO.

2
Community 23 Май 2017 в 10:32