Варіативна функція

функція зі змінним числом аргументів

У програмуванні, фу́нкції зі змі́нним число́м аргуме́нтів називають варіативними.

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

Приклад у C

ред.

Для реалізації функцій зі змінним числом аргументів у мові програмування C потрібно підключити заголовний файл  stdarg.h. Раніше використовувався varargs.h, який оголошено застарілим. Для C++ цей заголовний файл називається cstdarg[1].

#include <stdarg.h>

double average(int count, ...)
{
  va_list ap;
  int j;
  double sum = 0;

  va_start(ap, count); /* Потрібен останній відомий аргумент (щоб отримати адресу першого невідомного) */
  for (j = 0; j < count; j++) {
    sum += va_arg(ap, double); /* Збільшує ap до наступного аргументу. */
  }
  va_end(ap);

  return sum / count;
}

Ця функція дозволяє обчислити середнє значення від довільної кількості аргументів. Зверніть увагу, що функція не знає числа аргументів і їх типів. Функція з прикладу вище очікує, що типи будуть double і що число параметрів передається першим аргументом. В інших випадках, наприклад для функції printf(), число і типи аргументів з'ясовуються за рядком формату.

У загальному випадку варто знати про правило підвищення типів за замовчуванням, за яким підвищення типів зазнають усі аргументи функції, включно з невідомими аргументами. Так, якби в прикладі вище невідомі аргументи були оголошені типу float, фактично вони б виявилися типу double, і очікувати функція мала б тип double, а не float. Це може спричинити плутанину й помилки, якщо функція очікує аргумент певного розміру, а отримує аргумент іншого розміру. Особливо небезпечним є використання макроса NULL у варіативних функціях, оскільки NULL у C визначається конкретною реалізацією і не зобов'язаний бути нулем, зведеним до типу void *, а в C++ визначений як 0 без явного зведення до вказівника. Число 0 має тип int, найменший розмір якого відповідає 16 бітам (2 байти), що, найпевніш, не відповідатиме розміру очікуваного у функції вказівника.

stdarg.h оголошує тип va_list, і визначає чотири макрофункції: va_start, va_arg, va_copy і va_end. Кожному виклику va_start і va_copy має відповідати виклик va_end. Під час роботи зі змінним числом аргументів функція зазвичай оголошує змінну типу va_list (ap у прикладі), якою маніпулюватимуть макроси.

  1. va_start приймає два аргументи: об'єкт va_list  і посилання на останній параметр функції (той, що перед трикрапкою). Вона ініціалізує об'єкт va_list для використання у va_arg або va_copy. Компілятор зазвичай виводить попередження, якщо посилання хибне (наприклад, посилання на параметри, що відрізняються від останнього, або посилання на зовсім інший об'єкт).
  2. va_arg приймає два аргументи: об'єкт va_list (раніше ініціалізований) і дескриптор типу. Він розширюється на наступний аргумент і має вказаний тип. Кожен наступний виклик повертає наступний аргумент.
  3. va_end приймає один аргумент типу va_list і очищає його. Якщо потрібно, наприклад, опрацювати змінне число аргументів більш ніж один раз, слід повторно ініціалізувати va_list, викликавши va_end і потім va_start.
  4. va_copy приймає два аргументи, обидва типи va_list. Він дублює другий (який повинен був бути ініціалізованим) у перший.

Див. також

ред.

Примітки

ред.
  1. <cstdarg> (stdarg.h) — C++ Reference. Архів оригіналу за 31 жовтня 2012. Процитовано 29 березня 2022.

Посилання

ред.