Едино разовое объявление структуры в проекте

Есть, допустим, три файла:
blah.c blah.h main.c
в blah.h объявлена структура:
structure blah test_blah (...);
в blah.c она описана (и подключен файл blah.h).

В main.c подключен blah.h

В этом случае, при попытке скомпилировать эти файлы компилятор ругается об дублированном объявлении структуры test_blah.
Поэтому я пишу вместо structure blah test_blah (...);
static structure blah test_blah (...);

Но в таком случае создаётся 2 независимых экземпляра test_blahblah.c и main.c), что не желательно.

Как сделать так, чтобы был объявлен только 1 экземпляр test_blah в main.c
  • Вопрос задан
  • 7461 просмотр
Решения вопроса 1
@MikhailEdoshin
Вы переменную создаете, а не только структуру объявляете. test_blah — это переменная, тип данных struct blah. Задумывалось, наверное, так:

/* blah.h */
struct blah; /* урезанное описание */

/* blah.c */
#include "blah.h"
struct blah { int a, b } /* описание */
test_blah; /* и тут же объявление переменной этого типа */

/* main.c */
#include "blah.h"
/* можно работать с указателями на struct blah */
Ответ написан
Пригласить эксперта
Ответы на вопрос 3
@Door
Не «описание» и «описание», а объявление (declaration) и определение (definition).
Если у Вас есть тип (struct blah) и Вам нужен один экземпляр (instance) (в Вашем случае test_blah) этого типа, к которому нужно иметь доступ с любой точки программы, то Вам нужно один раз определить этот экземпляр (больше, конечно же, не получится, ODR. Определить — написать полное имя типа, указав имя переменной в одной единице трансляции), а перед использованием объявить, предварительно указав, что переменная (экземпляр) является «внешней» (extern) по отношению к текущей единице трансляции (обычно, это отдельный .cpp файл после препроцессора).

В итоге, у Вас есть, грубо говоря, 2 единици трансляции (blah.c, main.c). Нужно определить переменную в любой из них (в точке, конечно же, когда тип переменной определён, а не объявлён). И, для удобства (чтобы потом просто подключать заголовочный файл, а не каждый раз писать одно и то же) объявить переменную в blah.h, и подключая blah.h в любой, нужный .cpp файл, использовать её. Т.е.:

  1. // blah.h
  2.  
  3. #ifndef BLAH_H
  4. #define BLAH_H
  5.  
  6. // Объявляем и определяем тип (можно только объявить, а определить в другом месте)
  7. struct blah
  8. {
  9.     int value;
  10. };
  11.  
  12. // Объявляем переменную, указав, что она определена в другом месте
  13. // (Поскольку в данной точке мы имеем полное определение типа,
  14. // можно объявить blah_test типа struct blah, а если бы определение
  15. // находилось в другом месте (т.е. имели бы просто struct blah; выше), то пришлось бы
  16. // объявлять указатель на struct blah, т.е. struct blah*)
  17.  
  18. extern struct blah blah_test;
  19.  
  20. #endif
  21.  
  22. // ---------------------------------
  23. // blah.cpp (blah.c)
  24.  
  25.  
  26. #include "blah.h"
  27.  
  28. // Определяем переменную
  29. struct blah blah_test;
  30.  
  31. // ---------------------------------
  32. // main.cpp (main.c)
  33.  
  34. // Подключая заголовочный файл, объявляем переменную,
  35. // которую хотим использовать.
  36. #include "blah.h"
  37.  
  38. int main()
  39. {
  40.     // Используем
  41.     blah_test.value = 0;
  42.  
  43.     return 0;
  44. }
  45.  
  46.  
Ответ написан
@Osmin
В blah.h должен быть define-guard. Т.е. в начало надо добавить:
#ifndef BLAH
#define BLAH

А в конец:
#endif
Ответ написан
AxisPod
@AxisPod
В голом C использовать extern, в C++ синглтон.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы