Как получить доступ к правильной глобальной переменной в C? - PullRequest
3 голосов
/ 15 января 2010

Допустим, у меня есть некоторый глобальный var GLOBAL в main.c, но у моего main.c есть #include "other.h". Но other.h также имеет глобальную переменную GLOBAL.

Как мне сообщить компилятору, что я имел в виду, когда пишу GLOBAL в main. Есть ли ключевое слово "this", которое я могу использовать?

Ответы [ 7 ]

10 голосов
/ 15 января 2010

В программе на Си не может быть двух глобальных переменных с одинаковым именем. C может разрешить несколько определений в одной и той же области файла с помощью правила предварительное определение , но в любом случае все определения будут ссылаться на одну и ту же переменную . Итак, по-видимому, ваш вопрос основан на неверной предпосылке. Там нет вопроса "какой" здесь. У вас есть только одна переменная.

Например, у вас может быть последовательность определений области файла в единице перевода C

int i;
int i;
int i;

Это допустимо в C (в отличие от C ++), и все эти определения фактически определяют одну и ту же переменную, а не три разные переменные.

Конечно, если одна из переменных определена как локальная переменная (если это так, вы должны указать ее в своем вопросе) (кстати, почему она называется GLOBAL тогда?), То она скроет имя переменной, определенной в области файла (или любой более высокой области). В этом случае нет способа получить доступ к скрытому имени в C. Переименуйте локальную переменную, чтобы избежать скрытия глобальной.

То, что вы подразумеваете под "other.h также имеет переменную", также неясно. Что значит «имеет» в этом случае? Переменная определена в other.h? Или просто объявлено ? Если он только что объявлен, то на самом деле его нет. Если он определен там ... ну, тогда реальный вопрос: почему вы определяете переменные в файлах .h?

5 голосов
/ 15 января 2010

На самом деле у вас нет двух переменных. Существует только одна, вы либо получите ошибку компилятора (или компоновщика), если два модуля объявят один и тот же глобал с одинаковым именем, либо компилятор / компоновщик решит, что вы подразумеваете это как избыточные объявления одной переменной, и объедините их .

2 голосов
/ 15 января 2010

Как уже упоминалось, избегайте использования одинаковых имен глобальных переменных / функций. Возьмите за правило ставить перед ними префикс имени модуля. То есть MODULE1_state, MODULE2_state и т. Д.

Если глобальная переменная будет использоваться только внутри одного исходного файла, не объявляйте ее в соответствующем заголовочном файле. Вместо этого объявите его в верхней части исходного файла и используйте ключевое слово static. Переменные, которые должны быть доступны для других модулей, должны быть объявлены в заголовочном файле с помощью ключевого слова extern. То же относится и к глобальным функциям. Это помогает поддерживать ту же самую публичную / частную дисциплину, которую вы обычно используете в объектно-ориентированном языке, таком как C ++, Java, C # и т. Д.

Пример:

В module.h:

#ifndef MODULE_H /* Header guard */
#define MODULE_H

/* Declarations for entities that CAN be accessed by other modules,
   i.e. "public". */
extern int MOD_publicVariable;
extern void MOD_publicFunction(int arg);

#endif // MODULE_H

В модуле.c:

/* Definitions for entities that CAN be accessed by other modules,
   i.e. "public". */
int MOD_publicVariable = 42;
void MOD_publicFunction(int arg) {...}

/* Declarations for entities that CAN'T be accessed by other modules,
   i.e. "private". */
static double MOD_privateVariable = 12.34;
static void MOD_privateFunction1(void);
static void MOD_privateFunction2(void);

/* Function definitions. */
void MOD_privateFunction1(void) {
     int localVariable; /* This doesn't need the module prefix. */
     ....
}

void MOD_privateFunction2(void) {
     ....
}

Префикс модуля (MOD_) может быть назван сразу после вашего модуля, или вы можете использовать сокращение. Поэкспериментируйте, и вы в конечном итоге остановитесь на соглашении, которое вам нравится. Последовательное использование префикса, подобного этому, эмулирует концепцию класса / модуля / пространства имен в языках OO.

Убедитесь, что вы знаете разницу между объявлением и определением и внешним и статическим.

Меня раздражает, что учебники и курсы по Си игнорируют искусство мультимодульного программирования или приукрашивают его.

EDIT: Я забыл упомянуть, что вы вообще не должны делать глобальные переменные доступными для других модулей (то есть делать их «частными»). Если другие модули нуждаются в доступе к этой переменной, предоставьте функции «public» «setter» и / или «getter».

0 голосов
/ 15 января 2010

Прежде всего, если это проблема, во-первых, вы используете дрянную библиотеку и должны переписать / переключить, если это возможно. Если вы не можете, вы можете сделать что-то вроде этого:

other.h:

int GLOBAL;
//...other stuff

main.c

int GLOBAL;
#define GLOBAL OTHER_GLOBAL
#include "other.h"
#undef GLOBAL

int main(int argc,char** argv)
    {
    printf("%i %i",GLOBAL,OTHER_GLOBAL);
    getchar();
    return 0;
    }

однако, если подразумевать заглавные буквы, GLOBAL равно #define ed, это может не сработать. (Но все равно стоит попробовать.)

0 голосов
/ 15 января 2010

Возможно, это не тот ответ, который вы ищете, но почему бы вам не попытаться избежать подобных ситуаций вообще (и, возможно, (чрезмерно) использовать глобальные переменные)?

0 голосов
/ 15 января 2010

Я предполагаю, что вы определили переменную в программе, а не в препроцессоре, используя # define.

Если вы хотите сослаться на файл, созданный в main.c, просто наберите global. Для ссылки на них в вашем заголовочном файле используйте ключевое слово extern.

Вы бы лучше объявили их как два отдельных имени переменной, хотя, если честно.

0 голосов
/ 15 января 2010

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

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