Функции с переменным количеством параметров
Внимание! Это довольно старый топик, посты в него не попадут в новые, и их никто не увидит. Пишите пост, если хотите просто дополнить топик, а чтобы задать новый вопрос — начните новый.
Внимание! Это довольно старый топик, посты в него не попадут в новые, и их никто не увидит. Пишите пост, если хотите просто дополнить топик, а чтобы задать новый вопрос — начните новый.
Захотелось мне изучить функции с переменным количеством аргументов. В качестве практики решил сделать свой вариант функции
printf
. Код:Думаю алгоритм понятен. Но, естественно, если я пишу сюда, то код не работает. В чём проблема?
P.S.:
stdarg
не предлагать, зарежу :)Во-первых, ты зря отказываешься от
stdarg
. Функции с переменным числом параметров — штука очень зависимая от архитектуры процессора и компилятора.Во-вторых, ты не там ищешь необязательные аргументы. Искать надо в стеке, а не за концом форматной строки. Обычно (зависит от компилятора!) перед вызовом функции фактические параметры заносятся в стек, а потом вызывается функция. Например, вот такая программа:
у меня выдаёт:
Здесь первое число — адрес форматной строки. Далее 4 числа — необязательные аргументы функции (см. вызов функции в
main()
). Далее — мусор (для нас).Компилятор: TDM-GCC 4.8.1 64-bit Debug
Win7
Вот как у меня выводится ваша программа:
Компилятор
gcc
, 32bit, linux ubuntuА разве форматная строка также не передаётся через стек?
А, понял. Передаётся же не вся строка, а только адрес. Но ведь механизм передачи фактических параметров везде одинаков, а значит, беря адрес
format
, мы получаем адрес аргументов в стеке, тогда почему у меня такой вывод?Если пользоваться
stdarg
( видимо придётся резать себя:) ) и вот таким кодом:вывод верен.
Вот содержимое файла
stdarg.h
, я не могу понять, как он вообще что-то делает :) :Я не зря написал, что функции с переменным количеством параметров — штука сильно системозависимая, и специально указал свой компилятор и ось. Возможно для твоей системы тип
long long
надо заменить наlong
или даже наint
. У меня параметры в стеке получаются выровнены по границе 8 байт. У тебя, судя по выводу, — по границе 4 байт.Не факт. На 100% на это нельзя закладываться. Зависит от компилятора и архитектуры компьютера.
Там в конце вроде ещё должно быть
va_end()
?Собственно говоря, он объявляет тип
va_list
и определяет макросыva_...()
:А вот что делают функции
__builtin_va_...()
, сказать сложно — у меня нет исходников стандартных библиотек.да, это помогло
Я так понял, чтобы сделать программу без использования
va_...()
достаточно вместоlong long
указать тип, равный размеру машинного слова( только для системwindows
иlinux
).Но как тогда получать объекты, размер которых больше размера машинного слова?
А откуда берутся функции
__builtin_va_...()
их ведь нет ни в этом файле, ни в другом?Всё очень зависит от компилятора. См. документацию на конкретный компилятор.
Конечно, иметь понятие о всей этой внутренней кухне необходимо, но применять подобные трюки на практике сугубо не рекомендуется, поскольку они порождают непереносимый код.
Функции
__builtin_va_...()
берутся из Run-Time Library (RTL).Спасибо, Череп, всё как всегда доступно и качественно.
superUSer, зачем такая функция нужна?
cout
и так, вроде работает с типомstring
.Ради интереса попытался прогнать неопределённое количество параметров в
attiny2313
, не используяstdarg
( если он тут вообще есть :) ) Результат положительный, устройство работает как надо.Думаю после этого можно утверждать, что параметры везде передаются одинаково, по крайней мере языком
C
.Отщеплен новый топик «C++ и статическая типизация это прошлый век».