Вариадические функции - PullRequest
2 голосов
/ 17 августа 2011
#include <stdarg.h>
#include <stdio.h>

void varfun(int n,...){
va_list ptr;
int num;
va_start(ptr,n);
num=va_arg(ptr,int);
printf("\n%d",num);

}


int main(int argc, char **argv){

varfun(3,7.5,-11.2,0.66);

return 0;
}

Посмотрите на приведенный выше код, я ожидаю, что вывод будет первым значением параметра переменной, приведенным к int, то есть 7.5, приведенным к int, т.е. 7. Но выходной сигнал равен 0. Что не так в этом?

Ответы [ 4 ]

8 голосов
/ 17 августа 2011

va_arg не преобразует аргумент. интерпретирует как указанный тип. А если типы не совпадают, вы вызываете неопределенное поведение.

va_arg(ptr, int); /* take the next 4 bytes from the stack and interpret them as an `int` */
va_arg(ptr, double); /* take the next 8(?) bytes ... and interpret as double */
(int)va_arg(ptr, double); /* ... convert to int */

Также обратите внимание, что приведение в действительности не требуется в вашем фрагменте. Компилятор автоматически преобразует

void varfun(int n, ...) {
    va_list ptr;
    int num;
    va_start(ptr, n);
    num = va_arg(ptr, double); /* interpret as double, then convert to int */
    printf("%d\n",num);
}
3 голосов
/ 17 августа 2011

Ваш второй аргумент, 7.5, имеет тип double, но ваш вызов va_arg(ptr, int) трактует его как int. Это означает неопределенное поведение.

Функция variadic должна уметь определять количество и тип (ы) аргументов - и если вызывающий объект лжет, вам не повезло. printf -подобные функции делают это через строку формата; другие функции могут обрабатывать все свои аргументы как указатели и использовать конечный нулевой указатель в качестве часового.

1 голос
/ 17 августа 2011

Это на самом деле не приведение , а просто "чтение первых нескольких байтов" (*) переменной с плавающей запятой и рассмотрение ее как целого числа.

Вынужно прочитать этот аргумент как его действительный тип, тип double, а затем приведение к типу int.

num = (int) va_arg(ptr, double);

(*) Технически поведение, связанное с va_arg (ptr, неправильный_тип), равно undefined.«чтение первых нескольких байтов» - это фигура речи, описывающая только то, что обычно может произойти.Ни одна серьезная программа не должна полагаться на такие детали реализации.

0 голосов
/ 17 августа 2011

Он автоматически не преобразует значение 7,5 в int.Вам нужно будет использовать va_arg, чтобы получить значение как double, а затем выполнить приведение впоследствии.

va_arg(ptr,int) фактически ожидает, что значение, хранящееся в ptr, будет побитовым представлениемint, а это не так.

...