Как объявить встроенную функцию в многофайловом проекте 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
3 ответа
К сожалению, не все компиляторы полностью соответствуют 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);
Редактировать:
компиляторы с поддержкой C99 (обычно опция -std=c99
) что я знаю
- GCC (версии>= 4.3 IIRC) реализует правильный
inline
модель - ПКК тоже правильно
- ggc < 4.3 нужна специальная опция для реализации правильной модели, в противном случае они используют свою собственную модель, которая приводит к множеству определенных символов, если вы не будете осторожны
- icc просто испускает символы в каждой единице, если вы не будете особенно внимательны. Но эти символы являются "слабыми" символами, поэтому они не вызывают конфликта. Они просто взрывают твой код.
- opencc, AFAIR, следует старой специфической модели gcc
- лязг не испускает символы для
inline
функции вообще, если у вас нетextern
объявление, и вы используете указатель функции в одном модуле компиляции. - TCC просто игнорирует
inline
ключевое слово
Если используется сам по себе, в C99 inline
требует, чтобы функция была определена в том же модуле перевода, что и при использовании (поэтому, если вы используете ее в lib1.c, она должна быть определена в lib1.c).
Вы также можете объявить метод как static inline
(и поместите определение в заголовочный файл, общий для двух исходных файлов). Это позволяет избежать проблемы множественного определения и позволяет компилятору встроить файл во все блоки перевода, где он используется (что он может или не может сделать, если вы просто объявите функцию в одном блоке перевода).
Я думаю, что вам не нужно использовать встроенное слово, когда вы определяете и объявляете функцию внутри файла заголовка, компилятор обычно принимает его как встроенный по умолчанию, если только он не слишком длинный, и в этом случае он будет достаточно умен для обработки как нормальная функция.
Я думаю, что множественное определение может быть вызвано отсутствием функции "Включить охрану" в файле заголовка.
Вы должны использовать что-то вроде этого в шапке:
#ifndef HEADERNAME_H
#define HEADERNAME_H
void func()
{
// do things...
}
#endif