В примере 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по умолчанию, то ее вызов приведет к ошибке во время выполнения.
В примере 4 pfunобъявляется как указатель на farфункцию, возвращающую указатель на far double, после чего ему присваивается адрес функции fun. Такой вариант может использоваться, например, в компактной модели памяти для функции, которая используется редко, и потому необязательно должна находиться в стандартном сегменте кода. И функция, и указатель должны быть объявлены с модификатором far.
Читать дальше