![]() |
![]() |
Lexman 15.10.2004 - 19:49 |
Хотя, вероятнее что прикол у меня в голове, но всё же: ..Создал хедер с глобальными переменными, чтобы иметь доступ к ним из других модулей, просто подключив его. Использовал приличия ради конструкцию типа #ifndef _GlobalVars_ #define _GlobalVars_ .... здесь объявляем переменные .... #endif. ... Наивно подключаю этот файл в нескольких других модулях и при компиляции получаю ошибку, что мои переменные объявлены несколько раз (естественно, ссылка на одно и то же место - на этот самый хедер). Вот такая проблема. ... Кстати - речь идет об компиляторе CodeVision AVR 1.24 - прогрмамматор для контроллеров. |
Тигренок 1 - 15.10.2004 - 20:04 |
с помошью твоих макросов компилятор включил этот код в каждый объектник по одному разу (а не много раз). соотвестенно в каждом объектнике были объявлены эти переменные. переменные нужно объявить в одном объектнике (C/CPP файле): int myVar1; float myVar2; затем либо в каждом месте, где нужно, писать перед использованием extern int myVar1; extern float myVar2; либо создать *.H-файл, написать это там, и включать его где нужно... |
Lexman 2 - 16.10.2004 - 12:12 |
Собственно, *.Н я и написал (см. выше). При этом тоже надо extern использовать? А если этих переменных тысяча? :)) |
Тигренок 3 - 16.10.2004 - 13:37 | значит объявить 1000 переменных в C-файле и 1000 extern'ов для них в H :) |
Сергей 4 - 16.10.2004 - 13:48 |
Перечитай, что пишет Тигренок; тебе необходимо разобраться, как вообще происходит компиляция в С++, из каких стадий состоит, и тогда все станет понятно. Подробное описание этого процесса есть в любой вменяемой книге по языку С++. Попробую объяснить в двух словах. Процесс компиляции состоит из нескольких фаз: а) обработка кода препроцессором б) компиляция единиц трансляции в объектные файлы в) линковка объектных файлов в исполняемый модуль (для нас это .exe) Важно понимать, что сам по себе *.h-файл не компилируется; перед тем, как начать компиляцию, все файлы проекта обрабатываются препроцессором; при этом в текст *.срр полностью (!) и без изменений (!) включаются все *.h-файлы, которые подключены в него директивой #inсludе. Таким образом создаются "единицы трансляции"; они подаются на вход компилятору и компилируются раздельно, независимо друг от друга (принцип раздельной компиляции). Например, имеем файл prog.h: int x; int y; int z; И файл prog.cpp: // program example #inсludе "prog.h" int main() { return 0; } Тогда для компилятора единица трансляции "prog.cpp" будет выглядеть так: // program example int x; int y; int z; int main() { return 0; } Соответственно, если prog.h будет включен в десять разных .cpp, то и в них точно также будет включен тот же самый текст из prog.h. Что при этом будет происходить во время компиляции? Так как С++ компилирует единицы трансляции раздельно, то проблем не возникнет - просто в каждый объектный файл будут "физически" включены переменные x,y,z. Однако проблемы начнутся при линковке - на этом этапе компоновщик (linker) попытается связать вместе все получившиеся на этапе компиляции объектные файлы и выяснит, что в разных файлах имеются дублирующиеся переменные. Чтобы этого избежать, необходимо размещать переменные только в одной (!) единице трансляции, а в остальных указывать лишь "ссылки" на них. Делается это при помощи директивы extern. Она как раз и сообщает компилятору, что переменная с заданным именем и заданного типа станет доступной на этапе линковки из другой единицы трансляции, а в данной единице трансляции выделять под нее память не нужно. Таким образом, приведенный выше пример должен выглядеть таким образом: Файл prog.h: extern int x; extern int y; extern int z; Файл prog_global_data.cpp int x; int y; int z; Файл prog.cpp: #inсludе "prog.h" int main() { return 0; } В данном случае при компиляции получим две единицы трансляции - prog__global_data.cpp и prog.cpp; В первом объектом файле будет присутствовать реализация переменных x,y,z, а во втором, после включения prog.h, будут присутствовать "уведомления" компилятору о том, что переменные x,y,z имеют тип int и будут доступны на этапе линковки. Все. |
Сергей 5 - 16.10.2004 - 13:59 |
[2] "А если этих переменных тысяча?" К сожалению, глобальные переменные часто создают серьезные проблемы, особенно в крупных проектах, поэтому ситуация с таким количеством глобальных данных все же редкость. |
Lexman 6 - 16.10.2004 - 19:27 |
Все понятно :), я действительно не С-шник, но примерно так я себе проблему и представлял. Просто мне казалось, что в препроцессоре есть возможность отключить компиляцию части кода с помощью как-л. директив (см. пост 1). То что с глобальными переменными существуют сложности, это я вкурсе даже на своей шкуре, но вданном случае видимо придется смириться - так как хочется написать не удастся... Придется прописывать extern. Спасибо за консультацию! |