2009-12-28 3 views
1

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

GUIObject* factory(enumGUIType type, GUIObject* parent, ...){ 
    va_list vl; 
    va_start(vl, parent); 
    ... 
    label->SetPosition(va_arg(vl, int), va_arg(vl, int)); 
    va_end(vl); 
    return finalObjectPointer; 
} 

factory(LABEL, theParent, 100,200); // Results in position 200:200 

Что вызывает это неожиданное поведение?

+0

Использование функций va_arg - это скорее эксперимент, и я, вероятно, не буду использовать его в своем графическом интерфейсе, но было бы интересно узнать, что из этого вышло. – Zoomulator

ответ

6

Компилятор не может оценивать аргументы по порядку. Добавьте несколько дополнительных локальных переменных и выполните два назначения в последовательности.

См. this другие публикации переполнения стека.

int v1 = va_arg(vl, int); 
int v2 = va_arg(vl, int); 

label->SetPosition(v1, v2); 

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

2

Между оценками разных аргументов нет точек последовательности, поэтому при изменении аргументов при изменении аргументов необходимо изменить одно и то же значение (vl или что-то, что оно ссылается), в то время как оценка аргументов приводит к неуказанному поведению.

va_arg изменяет внутреннее состояние vl, чтобы зарегистрировать, какие аргументы уже обработаны, и при выполнении этого дважды во время оценки аргумента неуказано, что произойдет. Ваш компилятор и его оптимизаторы, похоже, приводят к передаче двух одинаковых параметров.

6

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

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

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