Как объявить встроенную функцию в многофайловом проекте C99? - PullRequest
25 голосов
/ 08 марта 2011

Я хочу определить встроенную функцию в проекте, скомпилированном с 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 ]

26 голосов
/ 08 марта 2011

К сожалению, не все компиляторы полностью соответствуют 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 модель
  • ПКК также правильно
  • ggc <4.3 требуется специальная опция для реализовать правильную модель, в противном случае они используют свою собственную модель что приводит к множественному определению символы, если вы не осторожны </li>
  • icc просто испускает символы в каждой единице если вы не будете особенно внимательны Но эти символы являются «слабыми» символами, поэтому они не порождают конфликт. Oни просто взорви свой код.
  • opencc, AFAIR, следует старой специфической модели gcc
  • clang вообще не генерирует символы для inline функций, если только у вас нет extern объявлений и , вы используете указатель функции в одной единице компиляции.
  • tcc просто игнорирует ключевое слово inline
4 голосов
/ 08 марта 2011

Если используется сам по себе, в C99 inline требует, чтобы функция была определена в той же единице перевода, что и при ее использовании (поэтому, если вы используете ее в lib1.c, она должна быть определена в lib1.c).

Вы также можете объявить метод как static inline (и поместить определение в файл заголовка, совместно используемый двумя исходными файлами). Это позволяет избежать проблемы множественного определения и позволяет компилятору встроить файл во все блоки перевода, где он используется (что он может или не может сделать, если вы просто объявите функцию в одной единице перевода).

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

0 голосов
/ 08 марта 2011

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

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

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

#ifndef HEADERNAME_H
#define HEADERNAME_H

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

#endif
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...