C: переменный список аргументов с использованием stdarg.h - PullRequest
2 голосов
/ 05 июня 2010

Я экспериментирую со списками переменных переменных и вижу странные результаты ...

Кусок кода, который я тестирую:

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

void foo(int param1, int param2, ...)
{
    int param3 = 0;

    va_list ap;
    va_start(ap, param2);
    param3 = va_arg(ap, int);
    va_end(ap);

    printf("param3: %d\n", param3);
}


int main(void)
{
  foo(1,1);
  foo(1,1,42);

}

И вывод для этого фрагмента:

param3: -1073748472
param3: 42

Для второго вызова: 'foo (1,1,42)', кажется, все работает как ожидалось.

Для первого вызова: 'foo (1,1)' результат выглядит как неинициализированный int, хотя я устанавливаю его равным 0, когда впервые инициализирую его в начале функции.

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

Есть предложения по этому поводу?

Большое спасибо.

Ответы [ 2 ]

8 голосов
/ 05 июня 2010

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

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

7 голосов
/ 05 июня 2010

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

При использовании varargs вы должны убедиться, что исходные аргументы, которые вы передаете, проясняют, какие другие аргументы присутствуют. printf () делает это путем подсчета знаков% (хотя программист иногда ошибается, и возникает веселье)

Лучший ответ: «не используйте varargs; найдите какой-нибудь безопасный для типов способ делать то, что вам нужно».

...