Страница 35 из 56
int pascal q(void); /* Функция типа pascal, возвращающая */
/* целое; параметры не передаются */
char far * s(char *source, int kind); /* Функция возвра- */
/* щает указатель типа far на строку,*/
/*а получает два параметра: типа char* и типа int */
int printf(char *format,...); /* Функция возвращает */
/* значение типа int, получая указатель */
/* на фиксированный параметр типа char */
/* и любое количество дополнительных параметров */
/* неизвестного типа */
- 285,286 -
int (*fp)(int); /* Указатель на функцию, возвращающую */
/* целое и получающую единственный */
/* целый параметр */
Ниже приводятся правила, регламентирующие работу с модифика-
торами языка и формальными параметрами в вызовах функций Турбо
Си, как использующих прототипы, так и не использующих их:
Правило #1. Модификаторы языка для описания функций должны совпа-
дать с модификаторами, используемыми в объявлении
функции, для всех обращений к функции.
Правило #2. Функция может изменять значения формальных парамет-
ров, но это не оказывает какого-либо воздействия на
значения действительных аргументов в вызывающей прог-
рамме, за исключением функций прерывания. Для большей
информации смотрите "Функции прерывания" в главе 12.
Если прототип функции не объявлен предварительно, то Турбо
Си преобразует целочисленные аргументы при обращении к функции
согласно правилам, приведенным в разделе "Арифметические преобра-
зования". Если прототип объявлен, то Турбо Си преобразует задан-
ные аргуметы к типу, назначенному для параметров.
Если прототип функции включает элипсис (...), то Турбо Си
преобразует все заданные аргументы функции как в любом другом
прототипе (до элипсиса). Компилятор будет расширять любые аргу-
менты, заданные после фиксированного числа параметров по нормаль-
ным правилам для аргументов функций без прототипов.
Если есть прототип, то число аргументов должно быть соответ-
ственным (за исключением случая, когда в прототипе использован
элипсис). Типы должны быть совместимы только по размеру, для
того чтобы корректно производились преобразования типов. Вы
всегда должны использовать явные преобразования аргументов к
типу, допустимому для прототипа функции.
Следующий пример прояснит данные замечания:
int strcmp(char *s1, char *s2); /* Полный прототип */
int *strcpy(); /* Нет прототипа */
int samp1(float, int, ...); /* Полный прототип */
samp2()
- 287,288 -
{
char *sx, *cp;
double z;
long a;
float q;
if (strcmp(sx, cp)) /* 1. Верно */
strcpy(sx, cp, 44);/* 2. Верно, но не переносимо из
Турбо Си */
samp1(3, a, q); /* 3. Корректно */
strcpy(cp); /* 4. Ошибка при выполнении */
samp1(2); /* 5. Ошибка при компиляции */
}
Пять вызовов (каждый с комментарием) примера демонстрируют
различные варианты вызовов функций и прототипов.
В вызове No 1 использование функции strcmp явно соответству-
ет прототипу, что справедливо для всех случаев.
В вызове No 2 обращение к strcpy имеет лишний аргумент
(strcpy определена для двух аргументов, а не для трех). В этом
случае Турбо Си теряет небольшое количество времени и создает код
для помещения лишнего аргумента в стек. Это, однако, не является
синтаксической ошибкой, поскольку компилятор не знает о числе ар-
гументов strcpy. Такой вызов не допустим для других компиляторов.
В вызове No 3 прототип требует, чтобы первый аргумент для
samp1 был преобразован к float, а второй - к int. Компилятор вы-
даст предупреждение о возможной потере значащих цифр поскольку
при преобразовании типа long к типу int отбрасываются старшие би-
ты. (Вы можете избавиться от такого предупреждения, если зададите
явное преобразование к целому.) Третий аргумент, q, соответствует
элипсису в прототипе. Он преобразуется к типу double согласно
обычному арифметическому преобразованию. Вызов полностью коррек-
тен.
В вызове No 4 снова вызывается strcpy, но число аргументов
слишком мало. Это вызовет ошибку при выполнении программы. Компи-
лятор будет молчать (если даже число параметров отличается от
числа параметров в предыдущем вызове той же функции), т.к. для
strcpy не определен прототип функции.
- 289,290 -
В вызове No 5 функции samp1 задано слишком мало аргументов.
Т.к. samp1 требует минимум два аргумента, этот оператор является
ошибочным. Компилятор выдаст сообщение о том, что в вызове не
хватает аргументов.
Важное замечание: если ваш прототип функции не соответствует
действительному определению функции, то Турбо Си обнаружит это в
том и только в том случае, если это определение находится в том
же файле, что и прототип. Если вы создаете библиотеку программ с
передаваемым набором прототипов (файлом include), то вы должны
учитывать включение файла с прототипами во время компиляции биб-
лиотеки, с целью выявления любого противоречия между прототипами
и действительными определениями функций.
Правила видимости (K&R 11)
-----------------------------------------------------------------
Турбо Си разрешает более свободное обращение с неуникальными
идентификаторами, чем того требует K&R. В Турбо Си различают че-
тыре класса идентификаторов:
Переменные, имена новых типов, описываемых с помощью
typedef, и перечисленные члены должны быть уникальными внутри
блока, в котором они описаны. Идентификаторы, объявленные внешни-
ми, должны быть уникальными среди переменных, описанных как внеш-
ние.
Имена структур, объединений и перечислений должны быть уни-
кальными внутри блока, в котором они описаны. Эти имена, описан-
ные вне пределов какой-либо функции, должны быть уникальны среди
всех соответствующих имен, описанных как внешние.
Имена членов структуры и объединения должны быть уникальны
в структуре или объединении, в которых они описаны. Не существует
никаких ограничений на тип или смещение для членов с одинаковыми
именами в различных структурах.
- 291,292 -
Метки на которые ссылаются операторы goto должны быть
уникальными внутри функции, в которой они определены.
Команды управления трансляцией (K&R 12)
-----------------------------------------------------------------
Турбо Си поддерживает все управляющие команды, описанные в K
&R. Этими командами являются директивы препроцессора - строки ис-
ходной программы, начинающиеся со знака #, за которым или перед
которым может следовать символ пробела или табуляции.
Замена лексем (K&R 12.1)
-----------------------------------------------------------------
Турбо Си поддерживает определения K&R для #define и #undef
со следующими дополнениями:
1. Ниже приведенные идентификаторы не должны встречаться в