2016-10-28 2 views
0

Я искал способ, чтобы пройти неопределенное количество аргументов функции, когда я наткнулся на способе сделать это с помощью va_list, va_start и va_end из stdarg.h как показано в приведенной программе here.

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

Способ использования va_list из файла заголовка stdarg.h является последовательным доступом к аргументам. Как только один аргумент читается, нет возврата.

Есть ли способ случайного доступа к этим аргументам?

EDIT: Мне было предложено опубликовать код вместо ссылки на содержащую его страницу. Итак, вот оно:

#include <stdarg.h> 
#include <stdio.h> 

/* this function will take the number of values to average 
followed by all of the numbers to average */ 
double average (int num, ...) 
{ 
    va_list arguments;      
    double sum = 0; 

    /* Initializing arguments to store all values after num */ 
    va_start (arguments, num);   

    for (int x = 0; x < num; x++)   
    { 
     sum += va_arg (arguments, double); 
    } 
    va_end (arguments);     // Cleans up the list 

    return sum/num;      
} 

int main() 
{ 

    printf("%f\n", average (3, 12.2, 22.3, 4.5)); 
    /* here it computes the average of the 5 values 3.3, 2.2, 1.1, 5.5 and 3.3 
    printf("%f\n", average (5, 3.3, 2.2, 1.1, 5.5, 3.3)); 
} 
+2

Поместите каждый в массив? –

+0

@WeatherVane Я думал то же самое, просто выполняйте функцию, которая читает аргумент thoses внутри вашего va_list и сохраняет их в массиве? Возможно, это не то, что вы хотите сделать, но затем добавьте некоторые исправления. – xoxel

+1

Вам все равно нужно знать типы и количество аргументов (printf делает это, перебирая строку формата) BTW: также существует жесткий предел количества аргументов, которые может выполнять функция. – joop

ответ

1

Нет портативного способа сделать это.

Предположим, что ваша функция вызывается с тремя аргументами, int, a double и long double. Они могут иметь разные размеры.

Механизм va_arg преднамеренно скрывает основное расположение переменных параметров, поскольку оно может варьироваться от одной реализации к другой.

Но предположим, что типичная реализация может передавать аргументы в стеке один за другим. Ваша функция не будет знать, где в памяти третий аргумент long double, не зная размеров первых двух аргументов. И объем пространства, занимаемого каждым аргументом, может не соответствовать размеру этого аргумента; например, было бы удобнее выделить 64 бита для 32-битного аргумента.

<stdarg.h> преднамеренно обеспечивает довольно минимальный интерфейс для доступа к переменным аргументам. Он позволяет вам обращаться к ним только по порядку, и только если вы знаете тип каждого аргумента.

Если вы хотите сделать что-то подобное, вы можете написать функцию, которая принимает указатель на начальный элемент массива указателей, каждый из которых указывает на некоторую структуру данных, которая может содержать любой из нескольких типов (возможно, что-то вроде a tagged union). Но тогда вызывающий должен настроить эту структуру перед вызовом функции.

К счастью, это практически не проблема на практике. Я не могу придумать какой-либо конкретной причины, почему нужен для доступа к аргументам случайным образом.

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

+0

И если _were_ попытаться «отстать от« stdarg's back », имейте в виду, что на 64-битных платформах _some_ аргументов передаются в регистры, а остальные в стеке ([см. Этот вопрос и ответы] (http: //stackoverflow.com/q/40216160/2096401)). – TripeHound

Смежные вопросы