|
Программирование >> Перегруженные имена функций и идентификаторы
double far y; #pragma option -zE* -zF* И x, и y окажутся в сегменте COMBINED MYCLASS, без группы. Объявление ближних или дальних функций В некоторых случаях вам может потребоваться переопределить заданное по умолчание значение типа функции для модели памяти. Например, вы используете модель памяти large, и в программе имеется рекурсивная функция: double power(double x,int exp) if (exp <= 0) return(1); else return(x * power(x, exp-1)); Каждый раз, когда функция power вызывает сама себя, она должна выполнить дальний вызов, причем используется дополнительное пространства стека и число тактовых циклов. Объявив power как near, можно ускорить выполнение ее благодаря тому, что вызовы этой функции будут ближними: double near power(double x,int exp) Это гарантирует, что функция power может вызываться только из того кодового сегмента, в котором она компилировалась, и что все обращения к ней будут ближними. Это означает, что при использовании большой модели памяти (medium, large или huge) функцию power можно вызывать только из того модуля, в котором она определена. Прочие модули имеют свои собственные кодовые сегменты и не могут вызывать функции near из других модулей. Более того, ближняя функция до первого к ней обращения должна быть либо определена, либо объявлена, иначе компилятор не знает о необходимости генерировать ближний вызов. И наоборот, объявление функции как дальней означает генерацию дальнего возврата. В малых моделях кодовой памяти дальняя функция должна быть объявлена или определена до первого к ней обращения, что обеспечит дальний вызов. Вернемся к примеру функции power. Хорошо также объявить power как static, поскольку предусматривается вызывать ее только из текущего модуля. Если функция будет объявлена как static, то имя ее не будет доступно ни одной функции вне данного модуля. Объявление указателей near, far или huge Только что были рассмотрены случаи, в которых может понадобиться объявить функцию с другой моделью памяти, нежели остальная часть программы. Зачем то же самое может понадобиться для указателей? По тем же причинам, что и для функций: либо для улучшения характеристик быстродействия (объявив near там, где по умолчанию было бы far), либо для ссылки за пределы сегмента по умолчанию (объявив far или huge там, где по умолчанию бывает near). Разумеется, при объявлении функций или указателей с другим типом, нежели используемый по умолчанию, потенциально появляется возможность ошибок. Предположим, имеется следующий пример программы с моделью small: void myputs(s) char *s; int i; for (i = 0; s[i] != 0; putc(s[i]); main() char near *mystr; mystr = Hello, world\n ; myputs(mystr); Эта программа работает удовлетворительно, хотя объявление mystr как near избыточно, поскольку все указатели, как кода, так и данных, будут ближними (near) по умолчанию. Однако, что произойдет, если перекомпилировать эту программу с моделью памяти compact (либо large или huge)? Указатель mystr в функции main останется ближним (16-битовым). Однако, указатель s в функции myputs теперь будет дальним (far), поскольку по умолчанию теперь используется far. Это означает, что попытка создания дальнего указателя приведет к извлечению из стека двух слов, и полученный таким образом адрес, безусловно, не будет являться адресом функции mystr. Как избежать этой проблемы? Решение состоит в том, чтобы определить myputs в современном стиле Си: void myputs(char *s) { /* тело myputs */ Теперь при компиляции вашей программы Borland C++ знает, что myputs ожидает указатель на char. Поскольку компиляция выполняется с моделью large, то известно, что указатель должен быть far. Вследствие этого Borland C++ поместит в стек регистр сегмента данных (DS) и 16-битовое значение mystr, образуя тем самым дальний указатель. Если вы собираетесь явно объявлять указатели как far или near, не забывайте использовать прототипы тех функций, которые могут работать с этими указателями. Как быть в обратном случае: когда аргументы myputs объявлены как far, а компиляция выполняется с моделью памяти small? И в этом случае без прототипа функции у вас возникнут проблемы, поскольку функция main будет помещать в стек и смещение, и адрес сегмента, тогда как myputs будет ожидать приема только одного смещения. При наличии определений функций в прототипах main будет помещать в стек только смещение. Создание указателя данного адреса сегмент:смещение Как создать дальний указатель на конкретный адрес памяти (конкретный адрес сегмент:смещение )? Для этого можно воспользоваться встроенной библиотечной подпрограммой MK FP, которая в качестве аргумента воспринимает сегмент и смещение, и возвращает дальний указатель. Например: MK FP(segment value, offset value) Имея дальний указатель fp, вы можете получить значение сегмента полного адреса с помощью FP SEG(fp) и значение смещения с помощью FP OFF(fp). Использование библиотечных файлов
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |