Как объявить встроенную функцию в многостраничном проекте C99?
Я хочу определить встроенную функцию в проекте, скомпилированную с помощью c99. Как мне это сделать?
Когда я объявляю функцию в файле заголовка и даю детали в файле .c, определение не распознается другими файлами. Когда я помещаю явную функцию в файл заголовка, у меня проблема, потому что все файлы .o, которые используют ее, имеют копию определения, поэтому компоновщик дает мне ошибку "множественного определения".
То, что я пытаюсь сделать, это что-то вроде:
header.h
inline void func()
{
do things...
}
lib1.c
#include "header.h"
...
lib2.c
#include "header.h"
с помощью утилиты, которая использует как lib1.o, так и lib2.o
Ответы
Ответ 1
К сожалению, не все компиляторы полностью соответствуют C99 в этой точке, даже если они утверждают, что они будут.
Соответствующий способ сделать это
// header file. an inline declaration alone is
// not supposed to generate an external symbol
inline void toto(void) {
// do something
}
// in one .c file, force the creation of an
// external symbol
extern inline void toto(void);
Более новые версии gcc, например, будут работать с этим.
Вы можете уйти с ним для других компиляторов (претендентов), определив что-то вроде
#ifdef PRETENDER
# define inlDec static
# define inlIns static
#else
# define inlDec
# define inlIns extern
#endif
// header file. an inline declaration alone is
// not supposed to generate an external symbol
inlDec inline void toto(void) {
// do something
}
// in one .c file, force the creation of an
// external symbol
inlIns inline void toto(void);
Edit:
с поддержкой C99 (обычно опция -std=c99
), которую я знаю
- gcc (версии >= 4.3 IIRC) реализует
правильная модель
inline
- pcc также верен
- ggc < 4.3 требуется специальный вариант для
реализовать правильную модель,
в противном случае они используют свою собственную модель
что приводит к
символы, если вы не внимательны.
- icc просто испускает символы в каждом модуле
если вы не проявляете особой осторожности. Но
эти символы являются "слабыми" символами, поэтому
они не создают конфликта. Oни
просто взорвите свой код.
- opencc, AFAIR, следует старой специальной модели gcc
- clang не выделяет символы для функций
inline
вообще, если у вас нет объявления extern
, и вы используете указатель функции в одном модуле компиляции.
- tcc просто игнорирует ключевое слово
inline
Ответ 2
Если он используется сам по себе, в C99 inline
требуется, чтобы функция была определена в той же самой единицы перевода, что и она (поэтому, если вы используете ее в lib1.c, она должна быть определена в lib1.c).
Вы также можете объявить метод как static inline
(и поместить определение в файл заголовка, совместно используемый между двумя исходными файлами). Это позволяет избежать проблемы с множественным определением и позволяет компилятору встроить файл во все единицы перевода, где он использовался (что он может или не может выполнить, если вы просто объявите функцию в одной единицы перевода).
Смотрите: http://www.greenend.org.uk/rjk/2003/03/inline.html
Ответ 3
Я думаю, что вам не нужно использовать встроенное слово, когда вы определяете и объявляете функцию внутри файла заголовка, компилятор обычно принимает его как встроенный по умолчанию, если он слишком длинный, и в этом случае он будет достаточно умным рассматривать его как нормальную функцию.
Я думаю, что множественное определение может быть вызвано отсутствием функции Include Guard в файле заголовка.
Вы должны использовать что-то вроде этого в заголовке:
#ifndef HEADERNAME_H
#define HEADERNAME_H
void func()
{
// do things...
}
#endif