Как объявить встроенную функцию в многофайловом проекте 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 (и поместите определение в заголовочный файл, общий для двух исходных файлов). Это позволяет избежать проблемы множественного определения и позволяет компилятору встроить файл во все блоки перевода, где он используется (что он может или не может сделать, если вы просто объявите функцию в одном блоке перевода).

См.: http://www.greenend.org.uk/rjk/2003/03/inline.html

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

Я думаю, что множественное определение может быть вызвано отсутствием функции "Включить охрану" в файле заголовка.

Вы должны использовать что-то вроде этого в шапке:

#ifndef HEADERNAME_H
#define HEADERNAME_H

void func()
{
    // do things...
}

#endif
Другие вопросы по тегам