Я посетил техническое интервью несколько дней назад, и меня спросили Как функции сжатия компилятора C работают с переменным числом аргументов? Как он проходит в стеке?
Кто-нибудь знает или может это объяснить?
Спасибо, Dan
Я посетил техническое интервью несколько дней назад, и меня спросили Как функции сжатия компилятора C работают с переменным числом аргументов? Как он проходит в стеке?
Кто-нибудь знает или может это объяснить?
Спасибо, Dan
Насколько я знаю, с C...
функция звонящего толкает аргументы в стек в порядке справа налево.
вызывающий отвечает за удаление аргументов из стека после выполнения вызываемой функции. Вероятно, именно потому, что вызывающему абоненту гарантировано знать, сколько аргументов оно помещает в стек, а вызываемая функция может ошибиться.
P.S.: Вызывающие соглашения обычно специфичны для реализации. То, что я только что описал, называется конвенцией о вызове cdecl. Контрастируйте это с вызывающим соглашением, обычно известным как "stdcall", где вызываемая функция отвечает за удаление своих аргументов из стека. Из-за этого он не поддерживает списки аргументов переменной длины.
P.P.S.: Как прокомментировал пользователь nategoose, я не упомянул, как фактически используются списки переменных аргументов. См. документация POSIX для заголовка <stdarg.h>
для получения дополнительной информации.
Он реализует их с помощью макросов va_, например va_start. Именно то, что делают эти макросы, определяется реализацией - другими словами, оно будет варьироваться от архитектуры процессора до архитектуры и от компилятора к компилятору. Но они должны играть трюки с помощью стека вызовов вызова. Как правило, это будет связано с использованием адреса последнего именованного параметра в качестве базы, а затем доступа к переменным параметрам путем выполнения арифметики указателя на этой базе.
Насколько вам грустно, что у вас есть этот вопрос по техническому интервью, я буду предполагать, что правильным ответом будет:
Caller будет вызывать явные параметры для стека, подсчет переменных параметров и самих параметров. Тогда целевой функциональный код будет отвечать за всплытие всех параметров на основе прошедшего счетчика и его адрес стека.
И добавьте некоторые идеи, почему размещение этих параметров в отдельном массиве не удобно.
Посмотрите на va_start, va_arg и va_end. Здесь есть тонна информации об этом.