Ответ 1
Но как насчет children? stack?
goto
между функциями не имеет никакого смысла, если вы думаете о стеке. Что будет в стеке, когда вы прыгаете? Функции источника и назначения могут потенциально иметь разные аргументы и другое возвращаемое значение. К кому будет возвращаться новая функция? Будет ли его возвращаемое значение даже иметь смысл для вызывающего? Вызывающий вызывал функцию источника, а не функцию назначения.
Возврат к вызывающему абоненту?
Рассмотрим ваш пример:
int main()
{
test();
main_next:
printf("hello, world);
}
void test()
{
goto main_next;
}
Что происходит, когда выполняется goto
? Я предполагаю, что вы захотите, чтобы это вернуло стек обратно к вызывающей функции main()
. goto
фактически будет таким же, как return
, изменив стек вызовов из:
main() main()
| to
+--> test()
Но что, если вы хотите перейти к функции, которая не находится в стеке вызовов? Что тогда?
Или заменить текущую функцию?
Другая интерпретация заключается в том, что goto
заменит существующий вызов test()
на один на main()
. Стек вызова изменится с:
main() main()
| to |
+--> test() +--> main()
Теперь main()
рекурсивно вызывает себя, а нижний main()
вернется к верхнему main()
— кто, кстати, ожидает возвращаемое значение void
, но получит int
.
setjmp и longjmp
Ближе всего вы можете получить setjmp
/longjmp
. Они позволяют сохранять и восстанавливать контекст стека для нелокальной пересылки, позволяя вам переходить между вызовами функций.
setjmp
и longjmp
обойти проблемы, описанные в (a) сохранении и восстановлении полного контекста стека при прыжке, и (b) не разрешать переходы, если контекст стека уже недействителен. Я цитирую из справочную страницу (внимание мое):
setjmp() и longjmp (3) полезны для устранения ошибок и прерываний, встречающихся в низкоуровневой подпрограмме программы. setjmp() сохраняет контекст/среду стека в env для последующего использования longjmp (3). Контекст стека будет недействительным, если функция, называемая setjmp(), вернется.
Другими словами, longjmp
является в основном эквивалентом C , бросающим исключение. Функция низкого уровня может развернуть стек вызовов и возобновить выполнение с гораздо более высокой функцией.
Это также ужасно сложно использовать, и редко хорошая идея. Снова, со страницы man:
setjmp() и sigsetjmp() делают программы трудными для понимания и поддержки. Если возможно, следует использовать альтернативу.