Не «описание» и «описание», а
объявление (
declaration) и
определение (
definition).
Если у Вас есть
тип (
struct blah
) и Вам нужен один
экземпляр (
instance) (в Вашем случае
test_blah) этого типа, к которому нужно иметь доступ с любой точки программы, то Вам нужно один раз определить этот экземпляр (больше, конечно же, не получится,
ODR. Определить — написать
полное имя типа, указав имя переменной в одной единице трансляции), а перед использованием объявить, предварительно указав, что переменная (экземпляр) является «внешней» (
extern) по отношению к текущей единице трансляции (обычно, это отдельный
.cpp файл после препроцессора).
В итоге, у Вас есть, грубо говоря, 2 единици трансляции (
blah.c,
main.c). Нужно определить переменную в любой из них (в точке, конечно же, когда тип переменной определён, а не объявлён). И, для удобства (чтобы потом просто подключать заголовочный файл, а не каждый раз писать одно и то же) объявить переменную в
blah.h, и подключая
blah.h в любой, нужный
.cpp файл, использовать её. Т.е.:
- // blah.h
-
- #ifndef BLAH_H
- #define BLAH_H
-
- // Объявляем и определяем тип (можно только объявить, а определить в другом месте)
- struct blah
- {
- int value;
- };
-
- // Объявляем переменную, указав, что она определена в другом месте
- // (Поскольку в данной точке мы имеем полное определение типа,
- // можно объявить blah_test типа struct blah, а если бы определение
- // находилось в другом месте (т.е. имели бы просто struct blah; выше), то пришлось бы
- // объявлять указатель на struct blah, т.е. struct blah*)
-
- extern struct blah blah_test;
-
- #endif
-
- // ---------------------------------
- // blah.cpp (blah.c)
-
-
- #include "blah.h"
-
- // Определяем переменную
- struct blah blah_test;
-
- // ---------------------------------
- // main.cpp (main.c)
-
- // Подключая заголовочный файл, объявляем переменную,
- // которую хотим использовать.
- #include "blah.h"
-
- int main()
- {
- // Используем
- blah_test.value = 0;
-
- return 0;
- }
-
-