c - 如何将 "goto"转换为 c 中的不同函数?

标签 c assembly calling-convention

基本上我是在尝试用 C 语言模拟汇编代码。

这是 C 代码:

int main()
{
   test();
main_next:
   printf("Hello, World!");
}

void test()
{
     goto main_next;
}

尝试编译此代码(Linux 32 位,gcc 4.6.3),出现此错误:

 error: label ‘main_randomtag_next’ used but not defined

有谁知道如何在 C 中执行这种过程间跳转?

谢谢!

最佳答案

但是 children? 堆栈呢?

如果您考虑堆栈,函数之间的

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()——who,顺便说一句,期待一个 void 返回值,但将收到一个 int

setjmp 和 longjmp

最接近的是 setjmp/longjmp .这些允许您保存和恢复非本地 goto 的堆栈上下文,允许您在函数调用之间跳转。

setjmplongjmp 解决了我描述的问题(a)在跳转时保存和恢复完整的堆栈上下文,以及(b)如果堆栈不允许跳转上下文不再有效。我引用自 the man page (强调我的):

setjmp() and longjmp(3) are useful for dealing with errors and interrupts encountered in a low-level subroutine of a program. setjmp() saves the stack context/environment in env for later use by longjmp(3). The stack context will be invalidated if the function which called setjmp() returns.

换句话说,longjmp 基本上是 throw an exception 的 C 等价物。低级函数可以展开调用堆栈并在更高级别的函数上恢复执行。

使用起来也非常棘手,而且很少是个好主意。同样,来自手册页:

setjmp() and sigsetjmp() make programs hard to understand and maintain. If possible an alternative should be used.

关于c - 如何将 "goto"转换为 c 中的不同函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21355110/

相关文章:

c++ - 避开 CRT

字符串的 C 和 Fortran 互操作性

delphi - 使用 ASM 调用对象方法 - 第 2 部分

c++ - 在这种特殊情况下,您会推荐使用程序集来访问参数吗?

在 linux 内核中使用 sprintf 将字符串转换为 int

c - Linux 字符设备驱动程序如何检测使用它的程序何时异常退出?

assembly - 我可以使用 rsp 作为通用寄存器吗?

assembly - 汇编器 - 从寄存器加载值而不是立即值

c++ - visual studio 中静态成员函数的默认调用约定是什么?

visual-studio-2008 - 为什么在 VS2003 中编译的 .lib 无法与使用 VS2008 编译的代码链接?