Logo Море(!) аналитической информации!
IT-консалтинг Software Engineering Программирование СУБД Безопасность Internet Сети Операционные системы Hardware
Бесплатный конструктор сайтов и Landing Page

Хостинг с DDoS защитой от 2.5$ + Бесплатный SSL и Домен

SSD VPS в Нидерландах под различные задачи от 2.6$

✅ Дешевый VPS-хостинг на AMD EPYC: 1vCore, 3GB DDR4, 15GB NVMe всего за €3,50!

🔥 Anti-DDoS защита 12 Тбит/с!

VPS в России, Европе и США

Бесплатная поддержка и администрирование

Оплата российскими и международными картами

🔥 VPS до 5.7 ГГц под любые задачи с AntiDDoS в 7 локациях

💸 Гифткод CITFORUM (250р на баланс) и попробуйте уже сейчас!

🛒 Скидка 15% на первый платеж (в течение 24ч)

Функции с изменяемым списком параметров

Для решения задачи передачи неопределённого количества параметров C++ располагает также средствами объявления переменных списков параметров.

Вспомним несколько форм Бэкуса-Наура, определяющих синтаксис списка параметров в определении и прототипе функции.

СписокОбъявленийПараметров ::= [СписокОбъявленийПарам] [...]
                           ::= СписокОбъявленийПарам, ...
СписокОбъявленийПарам ::= ОбъявлениеПараметра
                     ::= [СписокОбъявленийПарам,] ОбъявлениеПараметра

Таким образом, список объявлений параметров может завершаться многоточием, отделённым запятой от списка объявлений параметров, этого многоточия в списке параметров может не быть, а возможно также, что кроме многоточия в списке параметров вовсе ничего нет.

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

В этом случае количество и тип параметров становятся известны из списка выражений, определяющих значения параметров в выражении вызова функции.

Рассмотрим прототип и определение функции с переменным количеством параметров.

int PP(…);
int PP(…)
{
 return 100;
}

Трансляция этого фрагмента кода не вызывает у транслятора никаких возражений. Многоточием в списке параметров он предупреждён о возможных неожиданностях.

Следующий фрагмент кода демонстрирует варианты выражений вызова функции PP().

int retVal;
retVal = PP();
retVal = PP(1,2 + retVal,3,4,5,25*2);
PP('z',25,17);

В ходе выполнения выражений вызова функций с переменным количеством параметров изменяется алгоритм формирования записи активации. Теперь он выглядит примерно так:

  • в стековом сегменте выделяется запись активации. Теперь размер записи активации зависит от количества и типа параметров в выражении вызова, (а не прототипа). Так что сначала нужно определить и запомнить общее количество и тип выражений, которые образуют список параметров в выражении вызова функции. Как и раньше, вычисление значений производится в процессе выполнения программы. Как и раньше, значение параметра может быть представлено любыми выражениями;
  • на основе анализа прототипов вызываемой функции, расположенных в области видимости вызывающей функции, определяются начальные значения параметров (если они имеются), которые и записываются в соответствующие области записи активации. Как мы увидим дальше, в функциях с переменным количеством параметров слева от многоточия всё же может находиться хотя бы один явным образом определённый параметр. В противном случае просто не будет возможности воспользоваться значениями параметров;
  • вычисляются значения выражений, которые образуют список параметров в выражении вызова. Поскольку вычисление значений производится в ходе выполнения программы, здесь также нет никаких ограничений на процесс определения значения выражений. Можно использовать любые значения, а также вызовы ранее объявленных функций;
  • элементам записи активации присваиваются вычисленные значения. При этом возможно, часть параметров, которым были присвоены значения умолчания (это всегда ближайшие к многоточию параметры), получит новые значения. В этом процессе не допускается неопределённых ситуаций. Либо элемент записи активации получает значение умолчания, либо ему присваивается значение при вызове. Нарушение порядка означивания, как и раньше, выявляется ещё на стадии трансляции программы;
  • в вызываемой функции всем параметрам, которые были указаны в списке параметров, присваиваются значения из записи активации. Для остальных (непостоянных и, естественно, безымянных) параметров выделяется дополнительная память. Эти параметры также получают свои значения из записи активации;
  • управление передаётся первому оператору функции. Означенные параметры используются как переменные с определёнными значениями. Доступ к безымянным параметрам, в силу того, что к ним невозможно обращение по имени, обеспечивается специальными алгоритмами.

Итак, параметрам вызываемой функции присвоены соответствующие значения, представленные в выражении вызова. Возникает вопрос, как воспользоваться этими значениями в теле вызываемой функции. Если у параметра существует собственное имя, то всё очевидно.

Если же параметр был определён как параметр без имени, то существует единственный способ доступа к таким параметрам - доступ с помощью указателей.

Дело в том, что все означенные параметры, с именами и безмянные, занимают одну непрерывную область памяти. Поэтому для доступа к элементам этого списка достаточно знать имя и тип хотя бы одного параметра. Для этого в функции определяется указатель, которому с помощью операции взятия адреса присваивается значение, которое соответствует адресу именованного параметра. Переход от параметра к параметру при этом обеспечивается с помощью операций адресной арифметики над значением этого указателя.

С точки зрения реализации всё очень просто. Если бы не одно обстоятельство, которое заметно ограничивает свободу применения подобных функций.

Дело в том, что всякий раз при создании функций с неопределённым количеством параметров, мы вынуждены разрабатывать алгоритм доступа к списку этих самых параметров. А для этого необходимо, по крайней мере, представлять закономерность расположения параметров в списке. Так что список необъявленных параметров не может состоять из подобранных случайным образом элементов, поскольку не существует универсальных средств распознавания элементов этого списка. На практике дело обычно ограничивается несколькими тривиальными вариантами.

При этом либо известен тип и количество передаваемых параметров, и процедура доступа к параметрам сводится к примитивному алгоритму, который воспроизводится в следующем примере:

#include <iostream.h>
long PP(int n, ...);
void main (void)
{
long RR;
RR = PP(5, 1, 2, 3, 4, 5 );
/*
Вызвали функцию с 6 параметрами. Единственный обязательный параметр
определяет количество передаваемых параметров.
*/
cout << RR << endl;
}
long PP(int n ...)
{
 int *pPointer = &n;
  // Настроились на область памяти с параметрами...
 int Sum = 0;
 for ( ; n; n--) Sum += *(++pPointer);
 return Sum;
}

Либо известен тип элементов списка и признак завершения списка передаваемых параметров. Процедура доступа к параметрам также проста, как и в первом случае:

#include <iostream.h>
long PP(int par1 ...);
void main (void)
{
long RR;
RR = PP( 1, 2, 0, 4, 0 );
/*
Вызвали функцию с 5 параметрами. Единственный обязательный параметр -
первый параметр в списке параметров.
*/
cout << RRR << endl;
}
long PP(int par1 ...)
{
 int *pPointer = &par1;
/*
Настроились на область памяти с параметрами. Признак конца списка -
параметр с нулевым значением.
*/
 int Sum = 0;
 for ( ; *pPointer != 0; pPointer++) Sum += *pPointer;
// Что-то здесь не так… Мы так и не обработали до конца весь список.
 return Sum;
}

Назад | Содержание | Вперед

 

Скидка до 20% на услуги дата-центра. Аренда серверной стойки. Colocation от 1U!

Миграция в облако #SotelCloud. Виртуальный сервер в облаке. Выбрать конфигурацию на сайте!

Виртуальная АТС для вашего бизнеса. Приветственные бонусы для новых клиентов!

Виртуальные VPS серверы в РФ и ЕС

Dedicated серверы в РФ и ЕС

По промокоду CITFORUM скидка 30% на заказ VPS\VDS

VPS/VDS серверы. 30 локаций на выбор

Серверы VPS/VDS с большим диском

Хорошие условия для реселлеров

4VPS.SU - VPS в 17-ти странах

2Gbit/s безлимит

Современное железо!

Новости мира IT:

Архив новостей

IT-консалтинг Software Engineering Программирование СУБД Безопасность Internet Сети Операционные системы Hardware

Информация для рекламодателей PR-акции, размещение рекламы — adv@citforum.ru,
тел. +7 495 7861149
Пресс-релизы — pr@citforum.ru
Обратная связь
Информация для авторов
Rambler's Top100 TopList This Web server launched on February 24, 1997
Copyright © 1997-2000 CIT, © 2001-2019 CIT Forum
Внимание! Любой из материалов, опубликованных на этом сервере, не может быть воспроизведен в какой бы то ни было форме и какими бы то ни было средствами без письменного разрешения владельцев авторских прав. Подробнее...