C++ Builder
| Главная | Уроки | Статьи | FAQ | Форум | Downloads | Литература | Ссылки | RXLib | Диски |

 
Совсем неграмотный стал., Синтаксически.
iAlexander
  Отправлено: 23.09.2003, 17:46


Дежурный стрелочник

Группа: Участник
Сообщений: 70



Совсем плохо с мозгами. Объявил в Main.h 'глобальную' переменную Rate, могу присвоить ее в Main.cpp, но при попытке ее копирования в другом модуле ошибки не происходит, но копируется ноль. Хорошо, пример перед глазами. Сделал ее extern double Rate в .h и double Rate в .cpp. Теперь порядок. Но в чем же трабл?
Георгий
Отправлено: 23.09.2003, 21:37


Почетный железнодорожник

Группа: Модератор
Сообщений: 874



Препроцессор вставляет на место строки #include ... текст файла. Поэтому у тебя в первом случае фактически получилось, что каждый модуль, включивший этот файл заголовков, имеет свою личную переменную Rate.
Объявление переменной как extern в файле заголовков и обычное объявление переменной (могу ошибаться, но класс памяти этой переменной обязан быть static) с этим же именем в одном из файлов проекта приводит к тому, что редактор связей (linker) заменяет все обращения к переменной, для которой в файле есть только объявление extern, на обращения к той переменной имя которой совпадает с именем extern переменной, но не extern.
Примерный аглоритм работы компилятора и редактора связей:
дано:
CODE

1-й файл:
extern int Rate;
cout<<Rate;

2-й файл:
extern int Rate;
int Rate;
Rate=666;

после работы компилятора (пишу на псевдокоде):
1-й файл:
CODE

call operator<<(ostream&, extern int Rate);
т.е. написан код вызова функции, с аргументом, фактический адрес которого неизвестен
2-й файл:
Rate:=666
т.е. записать в переменную Rate значение (тут никаких неопределённостей нет)

работа редактора связей:
CODE

1-й и 2-й файлы фактически объединяются, после чего выполняется разрешение меток:
extern int Rate заменяется на адрес int Rate,
operator<<(ostream&, int Rate) заменяется на адрес библиотечной функции.

PS. С этим линкером у меня связана одна история:
Однажды наткнулся на глюк в BCB 5pro : в 2-х модулях были внутримодульные функции, прототип которых был полностью одинаков. В результате в конечном коде оказывалать только одна из них вместо 2-х, а у меня чуть волосы дыбом не стали — представьте себе вызывается функция с пустым телом ( int asd(void){return 0;} ), а значение она далеко не нулевое возвращает!!! Полтергейст блин!


Отредактировано Георгий — 23/09/2003, 22:41
Jean
Отправлено: 23.09.2003, 21:54


Дежурный стрелочник

Группа: Участник
Сообщений: 34



Хотя есть и плюс в таком подходе: у меня в каждом модуле есть функции, которые нужны для работы модуля, что-то вроде

CODE

void QueryOpen(TQuery *Query, AnsiString sSQL)
{
 Query->Close();
 Query->SQL->Text = sSQL;
 Query->Open();
}


И долгое время я копировал их в каждый модуль. А недавно обнаружилось, что в модулях, кроме главного, необходимо вставить лишь объявление этих функций. Потому как они все равно выполняются в главном модуле smile.gif

Обнаружилось при отладке — при обращении к функции, он лезет в главный модуль, хотя в данном присутствует аналогичная функция.
Георгий
Отправлено: 24.09.2003, 09:22


Почетный железнодорожник

Группа: Модератор
Сообщений: 874



Счастливчик — у тебя хоть код всех этих функций был одинаковый (по крайней меря я так понял), а у меня совершенно случайно 2 разных функции (они вызывались из одного моего обьекта для обработки данных — что-то вроде bsearch, qsort) были названы одинаково, но выполняли принципиально разные действия. И представляешь моё удивление, когда функция (алгоритм работы которой прост как программа Hello World) стала работать не правильно, а ещё больше я удивился, когда весь код этой функции заремил, а она продолжала работать, да и с той же ошибкой! Я такого никогда раньше не видел — пустая функция, а работает! Хорошо, что догадался, посмотреть, чтоже за функция вызывается вместо той, что была нужна.

Вернуться в Вопросы программирования в C++Builder