The OpenNET Project / Index page

[ новости /+++ | форум | теги | ]




Версия для распечатки Пред. тема | След. тема
Новые ответы [ Отслеживать ]
Интерфейс printf, !*! ghost_in_machine, 17-Янв-06, 19:42  [смотреть все]
Здравствуйте!
Хочу спросить у знающих людей о передаче параметров в функции на C. Вот есть очень удобный интерфейс у семейства функций printf(char *,...) но я нигде не могу найти как эти три точки принимает функция и преобразует в адреса переменных.
Спасибо большое.
  • Интерфейс printf, !*! veslo, 23:42 , 17-Янв-06 (2)
  • Интерфейс printf, !*! ghost_in_machine, 13:58 , 18-Янв-06 (3)
    Спасибо, veslo.
    Посмотрел я man и не сильно проникся. Есть ли какой-нибудь другой способ передать в функцию произвольный набор параметров без указаний их типов? Можно конечно каждый раз выделять память под структуру а-ля листа и складывать все адреса туда, но, может, есть способ решить проблему уже на этапе компиляции (компилятор то знает сколько параметров передают в конкретном вызове функции).
    Спасибо.

    • Интерфейс printf, !*! Аноним, 16:28 , 18-Янв-06 (4)
      >Есть ли какой-нибудь другой способ передать в функцию произвольный набор параметров без указаний их типов?

      Есть, но не в C.
      Вобщем используй va_arg, там ничего страшного.

    • Интерфейс printf, !*! Brick, 01:09 , 19-Янв-06 (5)
      >компилятор то знает сколько параметров передают в конкретном вызове  

      компилятор С ничего не знает про количество аргументов, переданных функции

      Почитать про этот механизм можно здесь:
      http://www.citforum.ru/security/articles/printf/
      http://www.intuit.ru/department/pl/c/9/4.html

      • Интерфейс printf, !*! Forth, 09:09 , 19-Янв-06 (6)
        >компилятор С ничего не знает про количество аргументов, переданных функции
        Почему? Знает. Иначе не смог бы отчистить стек по выходу из функции.


        • Интерфейс printf, !*! tilde, 09:26 , 19-Янв-06 (7)
          >>компилятор С ничего не знает про количество аргументов, переданных функции
          >Почему? Знает. Иначе не смог бы отчистить стек по выходу из функции.
          >

          Не знает. Стек очищает вызывающая функция. Поэтому вызванная функция может даже не знать общий размер всех параметров.

          • Интерфейс printf, !*! Forth, 09:39 , 19-Янв-06 (8)
            >Не знает. Стек очищает вызывающая функция. Поэтому вызванная функция может даже не
            >знать общий размер всех параметров.
            Ну да, вызывающая функция. А кто как не компилятор помещает в неё инструкцию отчистки стека? Я что-то не понимаю как может компилятор не знать про количество параметров, при том что он же помещение этих параметров в стек и компилирует. И потом после вызова функции вставляет очистку стека.
            Я думаю Вы что-то другое имели в виду.

            • Интерфейс printf, !*! ACCA, 12:05 , 19-Янв-06 (9)
              >>Не знает. Стек очищает вызывающая функция. Поэтому вызванная функция может даже не
              >>знать общий размер всех параметров.
              >Ну да, вызывающая функция. А кто как не компилятор помещает в неё
              >инструкцию отчистки стека? Я что-то не понимаю как может компилятор не

              Принимать произвольное число аргументов - свойство вызываемой функции, а не вызывающей. Компилятор ещё ничего не знает про вызывающую.

              Переменное число аргументов в современном C (C89 и новее) положено обрабатывать только с помощью stdarg, varagrs типа маст дай.

              Потрать полчаса на изучение - там ничего сложного.

              • Интерфейс printf, !*! Forth, 12:31 , 19-Янв-06 (10)
                > "компилятор С ничего не знает про количество аргументов, переданных
                > функции"
                Видимо имелось в виду "компилятор С _внутри вызываемой функции_ ничего не знает про количество аргументов, переданных этой функции" , а я подумал почему-то про вызывающую.:confuse:


        • Интерфейс printf, !*! ghost_in_machine, 12:57 , 19-Янв-06 (11)
          Спасибо всем за инфу. У меня возник вопрос по стеку. Если узнать адрес конца стека то функция типа f(int num,void** stack) будет именно тем что нужно. А можно ли в С узнать адрес стека? Будет ли это &num в принимающей функции?
          Спасибо.

          • Интерфейс printf, !*! ghost_in_machine, 13:00 , 19-Янв-06 (12)
            >Спасибо всем за инфу. У меня возник вопрос по стеку. Если узнать
            >адрес конца стека то функция типа f(int num,void** stack) будет именно
            >тем что нужно. А можно ли в С узнать адрес стека?
            >Будет ли это &num в принимающей функции?
            >Спасибо.
            Sorry должно быть f(int num,...)

            • Интерфейс printf, !*! Brick, 14:39 , 19-Янв-06 (13)
              >>Спасибо всем за инфу. У меня возник вопрос по стеку. Если узнать
              >>адрес конца стека то функция типа f(int num,void** stack) будет именно
              >>тем что нужно. А можно ли в С узнать адрес стека?
              >>Будет ли это &num в принимающей функции?
              >>Спасибо.
              >Sorry должно быть f(int num,...)
              да, именно, &num и будет адресом начала стека, а вот с концом, там уже самому надо выдумывать, почитай, я выше давал ссылки,там описывается этот механизм, а вообще, выше писали, для этого есть стандартные решения
              • Интерфейс printf, !*! ghost_in_machine, 15:29 , 19-Янв-06 (14)
                Спасибо Brick. Стандартные решения выглядят более запутанными. Я только немного не понял, возможен ли вариант каких-то пробелов между объектами из одного вызова или гарантированно они будут идти друг за другом согласно своим размерам. В ваших ссылках была пара туманных слов о запутанности структуры стека при работе современных компиляторов...
                Спасибо.  


                • Интерфейс printf, !*! Brick, 15:51 , 19-Янв-06 (15)
                  аргументы в стеке будут идти подряд, один за одним а для разбора параметров существует два класических приема:

                  1) Все аргументы должны быть одного и того же типа и используется какой-нибудь маркер конца списка аргументов, например, f1("arg1", "arg2", ... , "argN", "NULL"), где NULL и будет маркером конца аргументов.

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

                  • Интерфейс printf, !*! ghost_in_machine, 16:07 , 19-Янв-06 (16)
                    А что произойдет со стеком (его конкретным участком, содержащим параметры), если я вызову другую функцию внутри обработчика стека? Будут ли адреса стека и его элементов все еще валидными? И еще, как мне передать адрес стека в другую функцию, через void* или есть вариант для "три точки" -> "три точки" напрямую?
                    Спасибо.


                    • Интерфейс printf, !*! Brick, 16:41 , 19-Янв-06 (17)
                      >А что произойдет со стеком (его конкретным участком, содержащим параметры), если я вызову другую функцию внутри обработчика стека? Будут ли адреса стека и его элементов все еще валидными?
                      с адресами юудет вс
                    • Интерфейс printf, !*! Brick, 16:48 , 19-Янв-06 (18)
                      >А что произойдет со стеком (его конкретным участком, содержащим параметры), если я вызову другую функцию внутри обработчика стека? Будут ли адреса стека и его элементов все еще валидными?
                      что касается адресов, то всё будет нормально, эти аргументы ничем не отличаются от обычных аргументов функции

                      >И еще, как мне передать адрес стека в другую функцию, через void* или есть вариант для "три точки" -> "три точки" напрямую?
                      да, через stdarg: https://www.opennet.ru/docs/RUS/glibc/glibc-7.html




Партнёры:
PostgresPro
Inferno Solutions
Hosting by Hoster.ru
Хостинг:

Закладки на сайте
Проследить за страницей
Created 1996-2025 by Maxim Chirkov
Добавить, Поддержать, Вебмастеру