2010-01-15 4 views
3

позволяет сказать, что у меня есть глобальный var GLOBAL в main.c, но у моего main.c есть #include "other.h". Но у other.h есть глобальный var GLOBAL.Как получить доступ к правильной глобальной переменной в C?

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

+3

Хороший пример того, почему переменные не определены в заголовочных файлах. :-) –

+2

Вы всегда должны * определять * глобальные переменные в файлах .c (это выделяет для них пространство) и * объявлять * их с помощью 'extern' в .h файлах (это делает их видимыми для других модулей). –

ответ

-1

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

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

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

+0

Прошу прощения, но это не делает для меня никакого смысла. Особенно предлагаемое использование 'extern' для ссылки на« переменную в файле заголовка »(???) – AnT

+1

«Ключевое слово extern указывает, что фактическое хранилище и начальное значение переменной сохраняется в другом месте» Я всегда делал глобальные переменные в C, как будто я хочу ссылаться на один, определенный в заголовке, он объявлен как extern переменная Если я хочу создать переменную local в исходном файле, я пишу с тем же именем, я просто создаю новую ссылку так: переменная Зачем вам нужен глобальный var в вашем главном в первое место выходит за меня, но это то, о чем просили. К сожалению, подсказки о заглавной буквы были #define d, что делает весь этот вопрос бессмысленным – JimiF

10

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

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

int i; 
int i; 
int i; 

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

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

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

+0

GLOBAL - глобальная переменная в обоих файлах, а не локальная переменная – SuperString

+0

Я знаю. 95% моего ответа посвящено ситуации, когда обе декларации являются * глобальными *. Ссылка на локальную декларацию сделана в виде примечания. – AnT

+0

Андрей, есть способ получить доступ к глобальной переменной, затененной локальным (скажем, функциональной областью) - повторно объявить ее как «extern» при меньшей области. – qrdl

0

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

+0

Технически стандарт требует одного определения. Приложение J распознает «общее расширение» стандарта, который является ужасным каламбуром (или, по крайней мере, двойным entender) из-за определений Fortran COMMON. –

0

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

0

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

other.h:

int GLOBAL; 
//...other stuff 

основной.с

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 издание, это может не сработать. (Но все равно стоит попробовать.)

+0

Несомненно, было бы проще и безопаснее просто переименовать 'GLOBAL' в main.c в' MY_GLOBAL' или подобное? Не нужны волосатые макросы. –

5

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

2

Как уже упоминалось, избегайте использования тех же глобальных имен переменных/функций. Примените к ним префикс имени модуля. То есть 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 

В module.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.

Убедитесь, что вы знаете разницу между декларацией и определением, а также extern vs. static.

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

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

+0

Мне нравится, что вы подчеркиваете разницу между * объявлением * в заголовке, который просто говорит, что существует переменная этого имени, и ее * определение * в module.c, которое фактически выделяет для него пространство (и которое, смутно, является также декларация). Я думаю, что это одна из нескольких вещей, которые OP отключает. –

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