Как реализуется компилятор C с переменным числом аргументов?

Я посетил техническое интервью несколько дней назад, и меня спросили Как функции сжатия компилятора C работают с переменным числом аргументов? Как он проходит в стеке?

Кто-нибудь знает или может это объяснить?

Спасибо, Dan

Ответ 1

Насколько я знаю, с C...

  • функция звонящего толкает аргументы в стек в порядке справа налево.

  • вызывающий отвечает за удаление аргументов из стека после выполнения вызываемой функции. Вероятно, именно потому, что вызывающему абоненту гарантировано знать, сколько аргументов оно помещает в стек, а вызываемая функция может ошибиться.


P.S.: Вызывающие соглашения обычно специфичны для реализации. То, что я только что описал, называется конвенцией о вызове cdecl. Контрастируйте это с вызывающим соглашением, обычно известным как "stdcall", где вызываемая функция отвечает за удаление своих аргументов из стека. Из-за этого он не поддерживает списки аргументов переменной длины.


P.P.S.: Как прокомментировал пользователь nategoose, я не упомянул, как фактически используются списки переменных аргументов. См. документация POSIX для заголовка <stdarg.h> для получения дополнительной информации.

Ответ 2

Он реализует их с помощью макросов va_, например va_start. Именно то, что делают эти макросы, определяется реализацией - другими словами, оно будет варьироваться от архитектуры процессора до архитектуры и от компилятора к компилятору. Но они должны играть трюки с помощью стека вызовов вызова. Как правило, это будет связано с использованием адреса последнего именованного параметра в качестве базы, а затем доступа к переменным параметрам путем выполнения арифметики указателя на этой базе.

Ответ 3

Насколько вам грустно, что у вас есть этот вопрос по техническому интервью, я буду предполагать, что правильным ответом будет:

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

И добавьте некоторые идеи, почему размещение этих параметров в отдельном массиве не удобно.

Ответ 4

Посмотрите на va_start, va_arg и va_end. Здесь есть тонна информации об этом.