Как реализованы списки аргументов переменной длины? - PullRequest
5 голосов
/ 27 декабря 2011

Что происходит внутри, когда вызывается функция, которая использует varargs? Сами аргументы хранятся в куче или в стеке, как и любые другие аргументы. Если в стеке, как это работает?

Ответы [ 3 ]

8 голосов
/ 27 декабря 2011

Это зависит от реализации.Но, скорее всего, аргументы помещаются в стек, один за другим (после продвижения аргументов по умолчанию).

va_start, va_arg и т. Д. Работают, просто проводя указатель по стекуи переосмысление битов как того типа, который вы просите.

5 голосов
/ 27 декабря 2011

Как было отмечено ранее, это зависит от реализации.

В соглашении о вызовах C (известном как cdecl) аргументы помещаются в стек в обратном порядке, поэтому:

void myfunc(int one, int two, int three)

будет выглядеть в стеке после его вызова (стек увеличивается вверх, к 0):

  .                .                0x00000000
  .                .
  .                .
  | current frame  |
  |----------------|
  | return address |
  |----------------|                   ^
  |    one         |                   | stack
  |----------------|                   | growth
  |    two         |                   | direction
  |----------------|                   |
  |    three       |
  |----------------|
  | previous frame |
         ...       
         ...                        0xFFFFFFFF

Итак, первый аргумент может быть извлечен первым (потому что мы знаем, что это местоположение, это как раз перед адресом возврата), и, надеюсь, он содержит достаточно информации о количестве других аргументов. Например, в printf(3) и связанных функциях вся информация о других аргументах присутствует в строке формата, которая является первым аргументом.

1 голос
/ 27 декабря 2011

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

Например, в Паскале аргументы в стеке извлекаются вызываемым объектом.Поскольку вызываемый не знает о количестве отправленных элементов, он также не может восстановить стек до своего предыдущего состояния.Вот почему невозможно реализовать varargs в Pascal.

...