Определение понятия подпрограммы и функции. Примеры стековых кадров. Параметры и возвращаемое значение функции. Переменное число принимаемых параметров. Время жизни и область видимости переменных. Ограничения на функции с переменным числом параметров.
Структуризация программы с целью удобства ее понимания и сопровождения Исправление ошибок, оптимизация, расширение функциональности в ПП автоматически отражается на всех ее вызовах Вынесение в ПП даже однократно выполняемого набора действий делает программу более понятной и ОБОЗРИМОЙПОНЯТИЕ функции - механизм вызова Вызов ПП делится на Подготовительные служебные действия вызывающей программы Собственно работу ПП Заключительные служебные действия вызывающей программы Каждому вызову ПП соответствует отдельная область памяти - стековый кадр Стековый кадр Существует на протяжении всего вызова ПП Включая вложенные вызовы других ПП Перестает существовать после завершения вызова ПП Стековым кадром могут пользоваться Программа ПП Другие ПП, вызванные из ПППОНЯТИЕ функции - механизм вызова Стековый кадр содержит Адрес возврата - адрес команды, которая получит управление после завершения работы (выхода ) из ПП Вычисляется процессором или компилятором Обычно адрес первой команды заключительных действий Параметры ПП - переменные ПП, значения которых вызывающая программа устанавливает перед вызовом Могут частично находиться в регистрах процессора Внутренние переменные ПП Результат работы ПП - ячейка памяти, значение которой устанавливается ПП перед выходом и после этого может использоваться вызывающей программой Может находиться в регистре ПРОЦЕССОРАПРИМЕРЫ стековых кадров void f( int * px ) {* px = 1; } int g() {int x; f(&x); return x; } int main () {int x = g(); return 0; } Стек в main main x main ret addr main ret value Стек в g g x g ret addr g ret value main x main ret addr main ret value Стек в f f px f ret addr f ret value g x g ret addr g ret value main x main ret addr main ret value Убывание АДРЕСОВПРИМЕРЫ стековых кадров int main () {int a[10], i; for (i=0;i ::= | ", ""... Лекцию 4) или компиляция функции закончится ошибкой Исполнением последней инструкции тела функции Результат работы функции в этом случае неопределен - возможно мы получим сообщение об этом от КОМПИЛЯТОРАПОНЯТИЕ функции - вызов Вызов функции имеет вид постфиксное-выражение (список-аргументов-выражений ) постфиксное-выражение Объявленный и/или описанный идентификатор функции Переменная типа указатель на функцию или выражение типа указатель на функцию Ранее необъявленный идентификатор Автоматически объявляет идентификатор как функцию, возвращающую int с неизвестным числом и типами параметров Источник ошибок список-аргументов-выражений Проверка соответствия числа аргументов-выражений и числа параметров функции Если число параметров известно, то строгая проверка Если переменное число параметров, то число аргументов-выражений >= числ о параметров Проверка соответствия типов аргументов-выражений и типов параметров функции Если типы известны, то строгая проверка и, возможно, неявное преобразование Если типы неизвестны, то float-> double целочисленное ПОВЫШЕНИЕПОНЯТИЕ функции - описание void my_f () {} // Старый синтаксис void my_g (void) {} // Новый синтаксис int my_fact (int n) {return n==0 ? Чему равно my_fact (5)? int my_fib (int n) {return n= число параметров до лексемы "..." Проверка соответствия типов аргументов-выражений и типов параметров функции До лексемы "..." строгая проверка и, возможно, неявное преобразование После лексемы "..." преобразование float-> double и целочисленное ПОВЫШЕНИЕДОСТУП к значениям параметров, переданных через "..." Заголовочный файл stdarg.h C89 и далее До С89 varargs.h va_list - значения параметров, переданные через "..." va_start - инициализация переменной типа va_list va_arg - извлечение значения очередного аргумента из значения переменной типа va_list и переход к следующему аргументу va_end - завершение работы с переменной типа va_list va_copy - копирование значения из одной переменной типа va_list в другую переменную типа va_list (С99 и С11)Пример #include # include void print _ int_args (int arg1, ...) {va_list ap ; int i ; va_start (ap , arg1 ); for (i = arg1; i >= 0; i = va_arg (ap , int )) printf ("%d ", i ); va_end (ap ); printf ("
"); } int main(void) {print _ int_args (-1); // что будет напечатано? print _ int_args (5, 2, 14, 84, 97, 15, 24, 48,-1); print _ int_args (84, 51,-1); // print _ int_args (); - синтаксическая ошибка или предупреждение // print _ int_args (84, 51); - ошибка времени исполнения print _ int_args (0.5 ,-1 ); // 0.5 -> 0 // print _ int_args (0.5 , 1.5,-1 ); - ошибка врем. исполнения для 1.5 return 0; }Ограничения на функции с переменным числом параметров Нельзя проверить, кончились ли значения параметров, переданные через "..." Используем какой-либо явный признак конца списка значений Нельзя передать все значения параметров, полученные через "..." , другой функции с переменным числом параметров Каждой функции с переменным числом параметров - аналогичную функцию с постоянным числом параметров, последний из которых va_list int printf (const char*f, ...) int vp
Вы можете ЗАГРУЗИТЬ и ПОВЫСИТЬ уникальность своей работы