Как определить и объявить глобальные переменные для использования библиотечным кодом? - PullRequest
1 голос
/ 11 сентября 2010

основной файл (prog.c):

#include "log.c"
#include "library.c"
static char * Foo;

Если некоторая переменная (char * Foo) определена в основном файле (prog.c), и это требуется функцией log.c, вызываемой из library.c, как правильно объявить Foo видимым из пространства имен log.c

Ответы [ 4 ]

3 голосов
/ 11 сентября 2010

Добавьте свое объявление в некоторый файл .h, который включен в оба файла .c.Определите его в одном из файлов.

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

Например, в prog.h:

extern char *Foo;

в prog.c:

#include "prog.h"
#include "log.c"
#include "library.c"

char * Foo;         // make sure that Foo has a definition

// some code probably wants to make Foo have a value other than NULL

в log.c:

//... other includes
#include "prog.h"    // and now Foo is a known name

// some code here is using the global variable Foo

Теперь, к плохим новостям.

Подобные действия создают связь между модулями prog.c и log.c.Эта связь увеличивает стоимость обслуживания вашего приложения в целом.Одна из причин заключается в том, что нет способа помешать другим модулям использовать глобальную переменную.Хуже того, они могут использовать его совершенно случайно, потому что его имя недостаточно наглядно.

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

Конечно, бывают случаи, когда межмодульная связь, подразумеваемая глобальными переменными, является приемлемой.Один вариант использования предназначен для общих применений.Например, если ваше приложение поддерживает параметр --verbose, который заставляет его болтать во время работы, то имеет смысл, чтобы флаг, установленный параметром и проверенный по всему коду, был глобальной переменной.

В SO, безусловно, есть вопросы, которые глубоко вникают в ловушки глобалов и дают рекомендации по их разумному использованию.

2 голосов
/ 11 сентября 2010

Обычно в вашу основную программу включается исходный код библиотеки:

#include "log.c"
#include "library.c"
static char * Foo;

(Точка с запятой необходима.)

Однако, учитывая то, что вы делаете, если «log.c» нужно увидеть объявление, вы можете просто сделать:

static char * Foo;
#include "log.c"
#include "library.c"

Теперь статическое объявление видно для «log.c» (и «library.c»).

Если вы перейдете к более обычной установке, то у вас будет код в «log.c» для доступа к глобальной переменной, объявленной в соответствующем заголовке (а не к статическим переменным файла).Однако такие зависимости (где файл библиотеки зависит от глобальной переменной) создают неудобства.Основная программа (или часть кода) должна предоставить определение переменной.Было бы лучше, чтобы код в «log.c» определял переменную, а (предполагаемый) заголовок «log.h» объявлял переменную, и тогда основная программа установила бы переменную соответствующим образом.Или, лучше, код в «log.c» предоставит функцию или несколько функций для управления переменной, а заголовок объявит эти функции, и основная программа будет использовать их.

1 голос
/ 11 сентября 2010

Простой ответ:

static char * Foo;
#include "log.c"
#include "library.c"

Что делает Foo видимым в log.c и library.c просто благодаря правилу "объявить перед использованием".

Однако, что вам действительно нужно знать, так это то, что это противный код! Вы совершили как минимум два грехов ; Использование глобальных переменных и непонимание использования раздельной компиляции и связывания .

1 голос
/ 11 сентября 2010

Вы хотите extern.Когда вы выходите за пределы имени переменной, вы даете «обещание», что переменная будет существовать, когда вы создадите ссылку.Вы хотите сохранить его в файле .c, но извлекать его в заголовке.Таким образом, он создается один раз в объектном файле .c.Вы не хотите, чтобы два разных .o использовали одно и то же имя для ссылки на разные места в памяти.(Как отмечалось выше, почти всегда неправильно требовать что-то подобное для библиотеки.)

Таким образом, в общем заголовке у вас будет

common.h

extern Foo bar;

Затем в prog.c

Foo bar;

А когда вы включили common.h в log.c, вы можете получить доступ к панели из prog.c

Обратите внимание, чтосильно отличается в C, чем в Java.В Java это глобально для класса и доступно для всех, даже без экземпляра класса.В С static означает, что переменная не видна за пределами модуля компиляции.

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