2016-08-30 4 views
0

В моем коде на C я хочу выставить статические переменные через встроенные функции, и таким образом избежать использования атрибута «extern», типа ООП в стандартном C. Однако я не могу его скомпилировать. Рассмотрим следующий код:подвергая статическую переменную встроенной функции

[[email protected] snippets]$ cat object.h 
inline int get_value(int index); 
[[email protected] snippets]$ cat object.c 
#include "object.h" 
static int data_array[32]; 

inline int get_value(int index) { 
    return data_array[index]; 
} 
[[email protected] snippets]$ cat app.c 
#include "object.h" 
void main(void) { 
    int datum; 

    datum=get_value(8); 
} 
[[email protected] snippets]$ gcc -c object.c 
object.c:5:9: warning: ‘data_array’ is static but used in inline function ‘get_value’ which is not static 
    return data_array[index]; 
     ^
[[email protected] snippets]$ ls -l object.o 
-rw-rw-r-- 1 niko niko 976 Aug 30 15:56 object.o 
[[email protected] snippets]$ gcc -c app.c 
In file included from app.c:1:0: 
object.h:1:12: warning: inline function ‘get_value’ declared but never defined 
inline int get_value(int index); 
      ^
[[email protected] snippets]$ ls -l app.o 
-rw-rw-r-- 1 niko niko 1368 Aug 30 15:56 app.o 
[[email protected] snippets]$ gcc -o app app.o object.o 
app.o: In function `main': 
app.c:(.text+0xe): undefined reference to `get_value' 
collect2: error: ld returned 1 exit status 
[[email protected] snippets]$ 

Можно ли получить доступ к статическим переменным каким-то образом за пределами файла они были объявлены через функцию инлайн, которая будет встраиваются в каждом .c файле он используется? Конечно, я могу просто объявить переменную «EXTERN»:

extern int data_array[]; 

и ссылаться на него непосредственно, но я хочу сделать это с помощью функции для имитации ООП в C без накладных расходов на вызов функции.

+4

C11 проект стандарт n1570: * 6.7.4 Функции спецификаторов 3 Инлайн определение функции с внешним связыванием не должен содержать определение понятия изменяемых объект со статикой или длительностью хранения потока и не должен содержать ссылку на идентификатор с внутренней связью. * – EOF

+0

@EOF слишком плохо ... Интересно, как люди моделируют ООП в C сквозными встроенными функциями? единственной жизнеспособной альтернативой были бы макросы, я думаю ... – Nulik

+0

Я не вижу, как макрос поможет в любом случае. Я не уверен, почему вы настаиваете на том, что функции являются встроенными. – EOF

ответ

2

Ваш код является незаконным (как в ISO C, так и в GNU C): тело функции, объявленной как inline, должно отображаться в той же единице перевода, что и любой вызов этой функции. Но в вашем коде он не отображается в app.c, поэтому вы получаете неопределенную опорную ошибку.

Кроме того, как указано в комментариях, в ISO C функция inline, которая также не является static, может не содержать массив с внутренней связью. (Я не знаю, какие правила GNU C находятся в этой области).

В комментариях вы говорите о таких вещах, как «накладные расходы CALL» и т. Д. Но это имеет мало или ничего общего с ключевым словом inline. Оптимизатор будет производить самый быстрый код, если вы используете переключатель оптимизации. Назначение ключевого слова inline заключается в том, чтобы позволить телам функций отображаться в файлах заголовков.

Одним из вариантов было бы отменить функцию как inline, а также использовать переключатели -O2 -flto с gcc.

Другой вариант - использовать функцию inline, но поместить тело функции в файл заголовка. В этом случае вам также понадобится использовать extern int data_array[]; и т. Д., Так как невозможно определить массив в файле заголовка. Прежде чем делать этот вариант, выберите read this page. Вот код, который совместит как с ISO C и GNU C:

// header file 
extern int data_array[]; 

static inline int get_value(int index) 
{ 
    return data_array[index]; 
} 

// source file 
#include "header.h" 

int data_array[32]; 
+0

@AnT this является ответом C (как я уже говорил «C» несколько раз в ответе, а не «C++»). См. C11 6.7.4/7 «Для функции с внешней связью применяются следующие ограничения: если функция объявлена ​​с помощью спецификатора функции' inline', то она также должна быть определена в той же единице перевода ». (6.2.3/5 описывает, что 'inline int get_value (int);' объявляет функцию с внешней связью). Теперь я изменил формулировку этого пункта в своем ответе; это законно для тела функции после вызова, но в пределах той же единицы. –

+0

Да, вы правы. Я думал о другом. – AnT

+0

@AnT Хорошо, мы можем удалить комментарии, если вам нравится –

Смежные вопросы