leo А еще можно заглянуть в исходники используемого компилятора. Или в исходники системных библиотек, ежели продукт в Enterprise-комплектации. Для Борланда это ...\Source\Rtl\Sys\... . Там даже комментарии есть S_T_A_S_ Гы, да и кодогенератор у них практически один, не удивительно, что Borland забило на разработку компилеров %) Ваши данные несколько устарели. Все прогрессивное человечество уже затаило дыхание, ожидая выхода Delphi 2005 Вот в соседнем треде все дот-нет да дот-нет - а нифига! Win32 в исполнении Борланда наносит ответный удар.
const int * p1 = new int[10]; int * const p2 = new int[10]; При этом p1 - указатель на постоянный объект, то есть нельзя (запрещает компилятор) писать *p1=1; Тем не менее, компилятор не будет противиться строке *((int*)p1)=1; При указанной инициализации это не вызовет ошибок при исполнении, так как operator new () вообще не знает, что собираются делать с выделенной памятью - так что выделяет память на read/write. (Впрочем, выделять память только на чтение вряд ли целесообразно). const type* - указатели используется в контекстах: const char* func1(void) - означает, что не стоит модифицировать возвращаемое значение; void func2(const char*a) - означает, что функция не должна модифицировать переданный аргумент. Хотя если очень хочется, то это можно изменить. Хотя обычно, если указывается const - значит, это зачем-нибудь нужно. По поводу взаимосвязи const* со средствами ОС: нет никакой связи! Можно брать const- и не const-указатели на read-only область - при этом возникнут проблемы при записи; можно брать const- и не const-указатели на read/write область - не будет никаких проблем. Слово const можно рассматривать только как подсказку, которую можно игнорировать. Второй случай int*const p1=new int[10] означает, что запросто можно делать следующее: int a=*p1;*p1=1;int*a1=p1; но нельзя p1=b1; Хотя и в этом случае можно сказать (int*)p1=b1;
CyberManiac > Что-то мне подсказывает, что последняя дельфи ничего не сможет откомпилировать, если нет csc.exe и al.exe =)
Все выше написанные мною вопросы разрешены, но на подходе новый: Напишем код: Class A { public: void setVariable(int Var){variable = var;} private: int variable; } когда в: int main() { A a1; A a2; } то в стеке будут созданы одна группа на 4 байта для а1 и вторая группа тоже из 4 байтов для а2. А в секции кода насколько я полагаю будет код метода setVariable берущего на себя скрытый указатель(так называемый this) на объект а1 или а2, в зависимости от ситуации. Так как же мне просмотреть в памяти реализацию и нахождение этого метода в памяти?
EvilsInterrupt setVariable в программе может вообще не оказаться, так как этот метод нигде не вызывается, а очень хороший компилятор в секцию кода один ret запишет
Ладно. А так: int main() { A a1; A a2; a1.setVariable(2); return 0; } Как тута, т.е. как в файле или в адрессном пространстве найти этот метод?
EvilsInterrupt Смотришь во что компилируется a1.setVariable(2) и в команде call как раз и будет написан адрес метода. Для вызова виртуальных методов будет написано что-то типа: Code (Text): mov reg,[this]; указатель на таблицу виртуальных функций call [reg+XX];XX - смещение адреса метода в таблице Тут, чтобы узнать реальный адрес, потребуется заглянуть в отладчик. А вообще если интересует как это все реализуется, включи генерацию листинга и посмотри. Только оптимизацию не забудь отключить, а то будет тяжело разбираться.
Black_mirror команде call как раз и будет написан Imho хороший компилятор метод, подобный указанному, превратит в inline.
q_q Ну тогда только листинг смотреть. Потому что иначе мы даже не сможем узнать о наличии такого метода, а будем думать что variable объявлена как public, или вообще локальный int 8)
EvilsInterrupt > "как в файле или в адрессном пространстве найти этот метод?" Если кратко: то в данном случае - также как бы ты искал обычную функцию - в отладчике или по листингу (а если ты в своей проге копаешься, то можешь в MessageBox вывести адрес своего метода). Лирическое отступление: Отличие вызова невиртуального метода от вызова обычной функции в том, что в метод неявно передается дополнительный параметр - указатель на экземпляр класса. С тонкостями СИ я не знаком, но дельфах по умолчанию используется тип вызова register (аналог сишного fastcall) с последовательностью передачи параметров EAX,EDX,ECX. Поэтому если бы setVariable была бы обычной функцией, то мы имели бы Code (Text): mov eax,2 call rel32 <font color="gray];= call setVariable, rel32 - смещение setVariable относительно инструкции, следующей за call </font><!--color--> а для метода будем иметь Code (Text): mov eax,[xxxxxxxx] <font color="gray];= mov eax,a1</font><!--color--> mov edx,2 call rel32 Если метод виртуальный, как уже было сказано, он вызывается через VMT. Указатель на VMT - это первые 4 байта экземпляра класса. Продолжая дельфийский пример получим: Code (Text): mov eax,[xxxxxxxx] <font color="gray];= mov eax,a1</font><!--color--> mov edx,2 mov ecx,[eax] <font color="gray];указатель на VMT</font><!--color--> call [ecx+disp] <font color="gray];disp - смещение указателя на наш метод в VMT</font><!--color--> И еще замечание: в дельфах можно легко получить адрес на нужный метод, если объявить его опубликованным (published). Наверняка что-то подобное есть и в СИ (по крайней мере если класс наследуется от базового предка, на котором строятся визуальные компоненты). В частности программка DeDe дельфийские проги раскладывает по полочками с именами опубликованных методов - очень удобно.
>Отличие вызова невиртуального метода от вызова обычной >функции в том, что в метод неявно передается >дополнительный параметр - указатель на экземпляр класса. >С тонкостями СИ я не знаком В C++ функции класса передается указатель на класс(this) в регистре ecx.
Господа, спасибо. Вот еще вопрос: Запись на си int a; int * b = &a; можно представить ввиде: a dd 0 mov esi,offset a А если написать так: int a; int & ra = a; то как это можно представить?
EvilsInterrupt Господа конечно рады помочь, но мне думается такие "вопросы" проще проверить самому, чем полдня ждать ответа. Пишешь тестовую программку, ставишь бряк в нужной точке и смотришь что получилось: или в интегрированном отладчике или в OllyDbg, или в каком другом. Для внешнего отладчика бряк создается ассемблерной вставочкой с int3 или db CCh. Просто, быстро и элемент исследования - может чего интересного обнаружишь и поделишься с мировой общественностью.
infern0 Неправда. В C++ есть такой тип как ссылка. EvilsInterrupt На уровне ассемблера код для ссылки будет аналогичен коду для указателя.