Выбрать главу

В примере 2 указан большой размер массива b, поскольку более вероятно, что программист будет модифицировать тип адреса объекта большой длины, который может не поместиться в текущий сегмент.

В примере 3, очевидно, скорость доступа к массиву а не является критичной; независимо от того, попадет он в стандартный сегмент или не попадет, обращение к нему всегда будет осуществляться по 32-битовому адресу. В примере 4 массиву b с помощью модификатора near явно назначен стандартный сегмент, с целью ускорения доступа к нему в большой модели.

В примере 5 массив а должен быть явно объявлен как huge, поскольку его размер превышает 64 Кбайта. Использование модификатора huge вместо выбора максимальной модели памяти в качестве стандартной позволяет сэкономить время доступа: только к массиву а обращение будет осуществляться по адресу типа huge, а все остальные данные будут размещаться в стандартном сегменте. Для обращения к массиву а может быть использован указатель ра из примера 6. Все арифметические операции над указателем ра (например, ра++) будут выполняться над всеми 32 его битами.

В примере 7 ра объявляется как указатель на near char. Указатель получает тип near по умолчанию, поскольку речь идет о малой модели. В примере 8 pb явно объявляется как указатель на far char. Он может быть использован, в частности, для доступа к символьному массиву, расположенному не в стандартном сегменте памяти. Например, ра может указывать на массив а из примера 1, а pb — на массив b из примера 2.

Хотя объявления ра в примерах 9 и 10 идентичны, в примере 9 ра объявляется как указатель на near массив указателей на тип far char, а в примере 10 ра объявляется как указатель на far массив указателей на тип far char.

В примере 11 pb объявляется как указатель на near массив указателей на тип far char. В примере 12 pb объявляется как указатель на far массив указателей на тип far char. В этих примерах употребление слов far и near изменяет действующие по умолчанию соглашения, связанные с моделями памяти; в отличие от примеров 9 и 10, объявления pb не зависят от выбранной модели памяти и в любой модели имеют одинаковый смысл.

Объявление функций

Правила применения модификаторов near и far в объявлениях функций аналогичны правилам применения их в объявлениях данных. Если непосредственно за модификатором следует имя функции, то данное ключевое слово определяет, в каком сегменте будет размещена функция. Например,

char far fun();

определяет fun как функцию, вызываемую по 32-битовому адресу и возвращающую тип char.

Если же непосредственно за специальным ключевым словом следует признак указателя (звездочка), то данное ключевое слово определяет тип адреса функций, которые могут вызываться через этот указатель. Например,

char (far *pfun)();

определяет pfun как указатель (32-битовый) на far функцию, возвращающую char.

Модификатор huge к функциям и указателям на функции неприменим.

Объявления функций должны соответствовать их определениям по набору и расположению модификаторов. Рекомендуется всегда использовать предварительные объявления функций со списками типов аргументов, чтобы компилятор мог выявить ситуации некорректного вызова функции.

Примеры:

char far fun(); /* пример 1: малая модель */

static char far *near fun(); /* пример 2: большая модель */

void far fun(); /* пример 3: малая модель */

void (far *pfun)() = fun;

double far * far fun(); /* пример 4: компактная модель */

double far* (far *pfun)() = fun;

В первом примере fun объявляется как функция, возвращающая char. Ключевое слово far в объявлении означает, что fun вызывается по 32-битовому адресу типа far.

Во втором примере fun объявляется как near функция класса памяти static, возвращающая указатель на far char. Такая функция в большой модели памяти может быть использована, например, как вспомогательная подпрограмма, которая вызывается часто, но только функциями из своего исходного файла. Поскольку все функции из одного исходного файла помещаются в один и тот же сегмент, они могут обращаться друг к другу по адресам типа near. Будет ошибкой, однако, передать адрес функции fun в качестве аргумента другой функции, расположенной за пределами сегмента, в котором определена fun, поскольку из другого сегмента функция fun не может быть вызвана.

В третьем примере pfun объявляется как указатель на far функцию, не возвращающую значения, а затем ему присваивается адрес функции fun. Фактически pfun может быть использован для доступа к любой функции, имеющей тип адреса far. Следует понимать, что если функция, вызванная через указатель pfun, не была объявлена с модификатором far, или не получила тип far по умолчанию, то ее вызов приведет к ошибке во время выполнения.