Подтвердить что ты не робот

Как объявить встроенную функцию в многостраничном проекте 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

4b9b3361

Ответ 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