Аргументы переменной длины в C - PullRequest
0 голосов
/ 26 февраля 2019

Почему я должен брать переменную типа int в функции c var_args?Например, printf - это встроенная функция, которая не требует объявления длины аргументов перед вводом различных переменных ...

Ответы [ 3 ]

0 голосов
/ 26 февраля 2019

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

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

Если все аргументы имеют одинаковый тип, вы можете использовать именованный параметр дляукажите количество передаваемых аргументов. Например, если вы передаете несколько строк:

void foo_strings (int n, ...) {
    va_list ap;
    va_start(ap, n);
    while (n--) {
        const char *s = va_arg(ap, const char *);
        foo(s);
    }
    va_end(ap);
}

Однако вы могли бы так же легко использовать NULL, чтобы указать, что больше нетстроки.Затем первый аргумент можно использовать для чего-то другого, например, для указания на функцию.

void foo_string (void (*foo)(const char *), ...) {
    va_list ap;
    va_start(ap, n);
    const char *s = va_arg(ap, const char *);
    while (s != NULL) {
         foo(s);
         s = va_arg(ap, const char *);
    }
    va_end(ap);
}
0 голосов
/ 26 февраля 2019

Ответ связан с соглашениями о вызовах компилятора.Вот несколько упрощенное объяснение:

По сути, когда компилятор встречает вызов функции с N аргументами, он генерирует код для помещения N аргументов в стек.
Когда компилятор компилирует функцию, которая принимает N аргументов,он генерирует код для удаления N аргументов из стека.

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

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

printf и семейство используют другой метод. Строка формата определяет, какой тип и сколько аргументов она будет использовать.

0 голосов
/ 26 февраля 2019

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

Однако функция должна сделать соответствующие вызовы для va_arg.Для этого у функции должен быть какой-то способ узнать, какие аргументы были переданы.Вы можете реализовать это требование любым удобным для вас способом, в том числе:

  • Использовать строку формата, содержащую спецификаторы преобразования, которые указывают типы аргументов, как printf.
  • Передать любойописание чисел и типов каждого аргумента.Закодируйте их все в одном массиве, передайте несколько аргументов, описывающих остальные, опишите один аргумент, затем получите этот аргумент, затем опишите следующий аргумент, затем получите этот аргумент и т. Д.
  • Выведите аргументы из операциифункция запрашивается для выполнения.Например, вызов open может принимать флаги, которые указывают, должен ли он создать файл или просто открыть существующий.Если он предназначен для создания файла, он может принять дополнительный параметр, указывающий права доступа, которые должны быть установлены для файла, тогда как, если он просто открывает существующий файл, он не будет принимать этот параметр.
...