В C, как я могу ограничить область действия глобальной переменной файлом, в котором она объявлена?
Я новичок в C. У меня перед собой книга, в которой объясняется "область действия" C, включая пример кода. Но код только объявляет и инициализирует переменную области файла - он не проверяет область действия переменной, например, пытаясь получить к ней доступ незаконным способом. Так! В духе науки я построил эксперимент.
файл bar.c
:
static char fileScopedVariable[] = "asdf";
файл foo.c
:
#include <stdio.h>
#include "bar.c"
main()
{
printf("%s\n", fileScopedVariable);
}
Согласно моей книге и Google, звонок printf()
должен потерпеть неудачу - но это не так. foo.exe
выводит строку "asdf" и завершается нормально. Я бы очень хотел использовать область видимости файлов. Что мне не хватает?
4 ответа
Вы включаете bar.c, что приводит к тому, что препроцессор буквально копирует содержимое bar.c в foo.c до того, как его коснется компилятор.
Попробуйте избавиться от включения, но при этом попросите компилятор скомпилировать оба файла (например, gcc foo.c bar.c
) и смотреть, как вы жалуетесь, как вы ожидаете.
Редактировать: я предполагаю, что основная путаница между компилятором и препроцессором. Правила языка соблюдаются компилятором. Препроцессор запускается перед компилятором и действует на те команды с префиксом #. Все, что делает препроцессор - это манипулирование простым текстом. Он не анализирует код и не пытается каким-либо образом интерпретировать его значение. Директива "#include" очень буквальная - она говорит препроцессору "вставить содержимое этого файла сюда". Вот почему вы обычно используете только #include для файлов.h (заголовок), и вы помещаете только прототипы функций и объявления переменных extern в заголовочные файлы. В противном случае вы в конечном итоге будете компилировать одни и те же функции или определять одни и те же переменные несколько раз, что недопустимо.
Это вызвано запутанными условиями. file scope
в C не означает ограничение привязки идентификатора только к одной единице перевода. Это также не означает, что область действия ограничена одним физическим файлом. Вместо, file scope
означает, что ваш идентификатор является глобальным. Семестр file
здесь относится к тексту, полученному в результате обработки всех #include
, #define
и другие директивы препроцессора.
В общем, область действия - это только концепция, вступающая в силу в пределах одной единицы перевода. Когда задействовано несколько компиляций, начинает происходить связывание.
Если вы объявите свою переменную области видимости файла static
затем он дает переменную внутреннюю связь, что означает, что она не видна за пределами этой единицы перевода.
Если вы не объявите это статически явно, или если вы объявите переменную области видимости файла extern
, то это становится видимым для других единиц перевода: те, кто объявит переменную области файла с тем же идентификатором, будут иметь ссылку на этот идентификатор для этой же переменной.
В вашем случае включение bar.c
в foo.c
вставляет определение fileScopeVariable
в переводимую единицу перевода. Таким образом, это видно в этом блоке.
Никогда не включайте.c файл, как вы это делаете. Язык допускает это, но C-кодеры просто не делают этого, так что вы запутаете людей, если сделаете это. Скорее всего, включая себя.
"#include" означает "Компилятор, перейдите к этому другому файлу и прикрепите его к началу этого файла перед тем, как начать компилировать мой код".
Однажды я потерял целый день в полной растерянности, потому что один из исходных файлов vxWorks сделал это. Я все еще нахожусь на них из-за этого.
Удалите вторую инструкцию включения. Как было сказано выше...
Перед компиляцией вашего кода компилятор предварительно обрабатывает его. На этом этапе он обрабатывает все инструкции, начинающиеся с "#", такие как #include, #define и т. Д.
Чтобы увидеть результат этого этапа, вы можете просто запустить 'gcc -E ' (если вы используете gcc).