Форум программистов, компьютерный форум, киберфорум
Наши страницы

C# для начинающих

Войти
Регистрация
Восстановить пароль
 
Леманофф
10 / 10 / 3
Регистрация: 28.04.2016
Сообщений: 277
#1

Праздный интерес про компиляцию, когда метод вызывает сам себя - C#

16.05.2016, 11:11. Просмотров 262. Ответов 12
Метки нет (Все метки)

После компиляции кода с рекурсией, исполняемый код метода(который вызывает сам себя) в памяти:
1)копируется n-раз линейно, а потом в каждом методе правиться адрес передачи результата в следующую копию. По цепочке ?
2)копируется n-раз матрешкой. Т.е. первый кусок сидит внутри второго куска когда, который сидит в 3-м куске когда ?
3)Не копируется. Создается n-раз отдельные участки памяти для return'ов каждой итерации рекурсии ?
4)Компилятор очень умный. Он транслирует рекурсию в цикл (циклы. Систему циклов любой иерархии) ?
5)Если количество вывозов заранее не известно,и зависит от входных условий, то как компилятор посчитает размер памяти для стека ?

Просто уже кушать не могу, как интересно.
0
Лучшие ответы (1)
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
16.05.2016, 11:11
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Праздный интерес про компиляцию, когда метод вызывает сам себя (C#):

Поток сам себя перезапускает - C#
Здравствуйте, возможно ли сделать так что бы при возникновение ошибки в потоке, что бы он сам себя перезапустил? Спасибо

Метод который вызывает разные методы - C#
Так вот.Есть метод,который в зависимости от того что я введу(имя метода например),должен вызывать другой метод. Думал использовать...

Почему делегат не вызывает метод без Invoke - C#
Есть такой код public delegate bool IsPlaying(); private readonly IsPlaying _isPlaying; Почему так не работает ...

Ошибки: Конструктор не может вызвать сам себя. Неоднозначный вызов следующих методов или свойств - C#
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace...

Как можно сделать, чтобы checkbox сам себя отметил, при сравнение вводимого текста? - C#
не нашел нигде об этом информации и сам не особо шарю, но делаю задание с ардуино и меткой nfc. и вообщем суть заключается в том чтобы...

Как сделать чтобы метод вызвал сам себя? - Java SE
Если файл существует нужно увеличить число в имени файла и запустить метод заново. Но при вызове метода пишет ошибку int k = 0; ...

12
kolorotur
Эксперт .NET
9104 / 7608 / 1209
Регистрация: 17.09.2011
Сообщений: 13,139
16.05.2016, 11:45 #2
Цитата Сообщение от Леманофф Посмотреть сообщение
После компиляции кода с рекурсией, исполняемый код метода(который вызывает сам себя) в памяти:
Цитата Сообщение от Леманофф Посмотреть сообщение
3)Не копируется. Создается n-раз отдельные участки памяти для return'ов каждой итерации рекурсии ?
Но не только для return'ов, а полный фрейм вызова, как и для любого другого метода.

Цитата Сообщение от Леманофф Посмотреть сообщение
Если количество вывозов заранее не известно,и зависит от входных условий, то как компилятор посчитает размер памяти для стека ?
Размер памяти для одного вызова метода известен на стадии компиляции.
Если метод вызывается много раз, то эта память просто будет выделяться много раз.

Добавлено через 14 секунд
Цитата Сообщение от Леманофф Посмотреть сообщение
Просто уже кушать не могу, как интересно.
Приятного аппетита!
1
Леманофф
10 / 10 / 3
Регистрация: 28.04.2016
Сообщений: 277
16.05.2016, 13:10  [ТС] #3
Цитата Сообщение от kolorotur Посмотреть сообщение
Но не только для return'ов, а полный фрейм вызова, как и для любого другого метода.
Т.е. блок кода запускается многократно, и то значение, что осталось где-то в памяти от его предыдущего запуска(выходные данные), он же использует для себя эти данные на входе ?
Т.е. роль данных за счет логики кода, двойная. Они , будучи полученными, за счет работы метода, и являющиеся результатом его, при последующем запуске кода, являются уже для этого n-го запуска аргументом ?

[(аргумент для нового запуска блока кода)=(return от предыдущего запуска блока кода)+(что-то делаем с ним)]*n раз в фрейме вызова ?
Правильно ?
0
kolorotur
Эксперт .NET
9104 / 7608 / 1209
Регистрация: 17.09.2011
Сообщений: 13,139
16.05.2016, 13:51 #4
Цитата Сообщение от Леманофф Посмотреть сообщение
блок кода запускается многократно, и то значение, что осталось где-то в памяти от его предыдущего запуска(выходные данные), он же использует для себя эти данные на входе ?
На каком входе?
Если функция вызывается рекурсивно, то для текущего вызова результат работы другой функции хранится в определенном месте, о котором она знает.
Вот она запустила другую функцию (даже если с тем же кодом, т.е. рекурсивный вызов), а потом просто достала нужное значение из известного регистра.

Цитата Сообщение от Леманофф Посмотреть сообщение
Т.е. роль данных за счет логики кода, двойная. Они , будучи полученными, за счет работы метода, и являющиеся результатом его, при последующем запуске кода, являются уже для этого n-го запуска аргументом ?
Ну как и с любым другим методом: результат работы одного метода может служить входным параметром другому методу.
А может и не служить, как например в функции вычисления факториала:
C#
1
2
3
4
5
int Factorial(int n)
{
   if (n <= 1) return 1;
   return n * Factorial(n - 1);
}
Здесь результат рекурсивного вызова не передается другому методу, а просто используется в качестве возвращаемого значения.

Цитата Сообщение от Леманофф Посмотреть сообщение
[(аргумент для нового запуска блока кода)=(return от предыдущего запуска блока кода)+(что-то делаем с ним)]*n раз в фрейме вызова ?
Правильно ?
Зависит от реализации функции
В примере с факториалом return от предыдущего запуска используется только для текущего return'a, а не для вызова другой функции.
1
Леманофф
10 / 10 / 3
Регистрация: 28.04.2016
Сообщений: 277
16.05.2016, 14:24  [ТС] #5
Цитата Сообщение от kolorotur Посмотреть сообщение
На каком входе?
Если функция вызывается рекурсивно, то для текущего вызова результат работы другой функции хранится в определенном месте, о котором она знает.
Функция или метод, и класс это абстрактные понятия ЯВУ.
Мне интересно понять, как блок кода в нативе на уровне команд цп может вызывать сам себя ? Или не может ?
очень упрощенно:
вот кусок кода метода.
1)101010
2)110101
3)110111
4)111001

По смещению 3), там будет перевод ЦП к выполнению 1) ? Так это же цикл получится !

На уровне ЯВУ очень даже все получается сладко и красиво. Не спорю.
Можно наворотить - мало не покажется.)))
0
kolorotur
Эксперт .NET
9104 / 7608 / 1209
Регистрация: 17.09.2011
Сообщений: 13,139
16.05.2016, 15:06 #6
Цитата Сообщение от Леманофф Посмотреть сообщение
Функция или метод, и класс это абстрактные понятия ЯВУ.
Так точно.

Цитата Сообщение от Леманофф Посмотреть сообщение
Мне интересно понять, как блок кода в нативе на уровне команд цп может вызывать сам себя ? Или не может ?
Ну вы же выше сами сказали, что функции, методы, классы и пр. — это понятия абстрактные.
Для процессора такого понятия как функции не существует, для него есть просто бесконечный ряд инструкций, которые он выполняет от включения до отключения.
То есть работает ЦП как типичная машина Тьюринга: тупо прет по инструкциям на бесконечной ленте. Это уже мы (программисты) разделяем для удобства: вот этот участок ленты пусть будет такой-то функцией.
Одна из возможных инструкций на этой ленте — переход на другой участок ленты, чем мы и пользуемся для вызова различных функций.
Сама функция — это набор инструкций, который можно разбить на три части:
1. Так называемый пролог (procedure prologue) — это сохранение состояния текущей функции, помещение в известное место аргументов вызываемой функции, помещение в известное место адрес инструкции, на которую нужно перевести выполнение после окончания работы функции.
2. Рабочая часть — это то, что программист наговнокодил в самом теле функции.
3. Эпилог (procedure epilogue) — это сохранение возвращаемого значения (если оно есть) в известном всем месте, очистка используемой функцией памяти, восстановление состояния, сохраненного в первой части и, наконец, переход на указанную в первой части инструкцию.

Под сохранением текущей информации в программах, где используется стек вызовов, подразумевается сохранение значения указателя на начало фрейма вызывающей функции (на х86 для этого используется регистр EBP — Extended Base Pointer).
Потом вызываемая функция увеличивает стек для хранения своих локальных переменных, в процессе перезаписывая значение ЕВР, делает свое дело, возможно вызывая другие функции, которые делают то же самое.
В конце работы функции стек отматывается назад, сохраненное значение опять записывается в ЕВР и осуществляется переход на указанный адрес.
Как видите, к моменту завершения работы вызванной функции состояние вызывающей точно такое же, как до вызова, что позволяет ей продолжать свою работу как ни в чем не бывало.

Так понятней, или совсем на инструкции разбить?
1
Леманофф
10 / 10 / 3
Регистрация: 28.04.2016
Сообщений: 277
16.05.2016, 15:50  [ТС] #7
Добавлено через 32 секунды
Цитата Сообщение от kolorotur Посмотреть сообщение
Так понятней, или совсем на инструкции разбить?
на инструкции пока не надо. Спасибо! Сам попробую разложить на упрощенной вымышленной машине.

Просто я тупо вижу, на более низком уровне, многократное выполнение набора одних и тех же команд (циклическое). В целом. По другому не получается.
Рекурсию вижу, но только на уровне языка высокого уровня. Т.е. абстрактно.
А значит пока не могу утверждать следующее имхо:
"для каждой рекурсивной функции существует тождественно равное циклическое представление логики".
А хотелось бы так утверждать.
0
kolorotur
Эксперт .NET
9104 / 7608 / 1209
Регистрация: 17.09.2011
Сообщений: 13,139
16.05.2016, 16:00 #8
Лучший ответ Сообщение было отмечено автором темы, экспертом или модератором как ответ
Цитата Сообщение от Леманофф Посмотреть сообщение
Просто я тупо вижу, на более низком уровне, многократное выполнение набора одних и тех же команд (циклическое). В целом.
Так и есть.

Цитата Сообщение от Леманофф Посмотреть сообщение
А значит пока не могу утверждать следующее имхо:
"для каждой рекурсивной функции существует тождественно равное циклическое представление логики".
А хотелось бы так утверждать.
Утверждайте смело — на уровне инструкций рекурсия — тот же самый цикл, но который может грохнуть стек
0
Леманофф
10 / 10 / 3
Регистрация: 28.04.2016
Сообщений: 277
16.05.2016, 20:53  [ТС] #9
Цитата Сообщение от kolorotur Посмотреть сообщение
Так и есть.

А я, блин, сижу, черчу схемки, ночи не сплю....Вот не пьющий, а так бы ...
Цитата Сообщение от kolorotur Посмотреть сообщение
Утверждайте смело — на уровне инструкций рекурсия — тот же самый цикл, но который может грохнуть стек

Вот теперь легче будет понимать.
Спасибо.
p.s.
просто не поняв, хоть что-то на чуть более низком уровне не могу дальше изучать - зуд какой то начинается.

Добавлено через 2 минуты
Цитата Сообщение от kolorotur Посмотреть сообщение
Приятного аппетита!
Ну вот теперь поел хорошо. Спасибо. Говядинки потушил основательно.
0
kolorotur
Эксперт .NET
9104 / 7608 / 1209
Регистрация: 17.09.2011
Сообщений: 13,139
16.05.2016, 22:40 #10
Цитата Сообщение от Леманофф Посмотреть сообщение
просто не поняв, хоть что-то на чуть более низком уровне не могу дальше изучать - зуд какой то начинается.
В таком случае рекомендую изучить ассемблер — сразу станет поняно что там и как происходит на самом низком уровне. Ниже — только опкоды и электросхемы.
1
Леманофф
10 / 10 / 3
Регистрация: 28.04.2016
Сообщений: 277
17.05.2016, 09:08  [ТС] #11
Цитата Сообщение от kolorotur Посмотреть сообщение
В таком случае рекомендую изучить ассемблер — сразу станет поняно что там и как происходит на самом низком уровне. Ниже — только опкоды и электросхемы.
эмулятор 8086 поставить или хватит вот этого:
https://schweigi.github.io/assembler-simulator/

Я тут глянул - очень много мнемоник в цикле щелкает долго долго, что бы только символ вывести (((
При этом возврат на метку loop по JNZ это же не низкий уровень вроде. Макросы и метки, это же вроде не фича процессора, а ассемблеровская. Хотя фиг знает. Надеюсь сами мнемоники это чисто железячный самый низкий уровень абстракции (конечно не двоичный).
0
kolorotur
Эксперт .NET
9104 / 7608 / 1209
Регистрация: 17.09.2011
Сообщений: 13,139
17.05.2016, 10:38 #12
Цитата Сообщение от Леманофф Посмотреть сообщение
эмулятор 8086 поставить или хватит вот этого
В принципе хватит и этого, но если хотите знать разницу между EBP и ESP, EAX и EDX и пр., а так же использовать их непосредственно в коде, то ставьте эмулятор х86.

Цитата Сообщение от Леманофф Посмотреть сообщение
очень много мнемоник в цикле щелкает долго долго, что бы только символ вывести (((
Ну добро пожаловать в мир низкоуровневого программирования

Цитата Сообщение от Леманофф Посмотреть сообщение
При этом возврат на метку loop по JNZ это же не низкий уровень вроде.
JNZ — это Jump if Not Zero, безусловный переход на метку, если предыдущая операция СМР не произвела ноль.
Метка — это просто адрес инструкции, в опкодах это будет число.

Цитата Сообщение от Леманофф Посмотреть сообщение
Макросы и метки, это же вроде не фича процессора, а ассемблеровская.
Ага.

Цитата Сообщение от Леманофф Посмотреть сообщение
Надеюсь сами мнемоники это чисто железячный самый низкий уровень абстракции (конечно не двоичный).
Ну ниже уже непосредственно опкоды.
Даже не ниже, команды ассемблера — это просто альясы для опкодов, ассемблер их тупо подменяет на двоичные числа, как и их аргументы.
1
Леманофф
10 / 10 / 3
Регистрация: 28.04.2016
Сообщений: 277
17.05.2016, 17:45  [ТС] #13
Изучаю.
Такое ощущение, что я готовлюсь стать настройщиком очень продвинутого автомата по продаже РАЗНОЙ газировки. Или около этого. Но почему то это интересно.
Кстати, сейчас наверное на языке ассемблера никто даже уже и системно не кодит. Кроме крохотной части ядра ос..Всё же на C уже наверное пишут. Ассемблер наверное нужен только для саморазвития)))
0
17.05.2016, 17:45
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
17.05.2016, 17:45
Привет! Вот еще темы с ответами:

Видимость переменных. Может ли метод вызывать сам себя? - Java SE
Такой вот вопросец появился. Имеем гипотетический метод с циклом for, который обрабатывает строку. Если внутри цикла вызвать этот же метод...

C++Builder 6 выдаёт ошибку когда выполняешь компиляцию - C++ Builder
Проект рабочий, просто когда хочешь внести изменения делаешь компиляцию выходит ошибка и пропадает ярлык, не знаю как быть, прошу...

вопрос новичка про компиляцию в Visual C++ - Visual C++
товарищи , помогите новичку ... скачал Visual C++ 2008 Express Edition, поставил, написал пару простеньких программ и тут встал вопрос ,а...

про раздельную компиляцию и заголовочные файлы - C++
Люди, кто-нибудь может просто и понятно объяснить мне про раздельную компиляцию и заголовочные файлы, плз!!!!


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
13
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru