微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

C调用约定并传递参数

在Linux(或OS X)中进行函数调用时,被调用者是否可以修改堆栈中参数的值? 我是在这样的假设下,因为调用者是清理它们的那个,所以在函数调用之后它们应该包含相同的值。 但是我发现使用-O2的GCC正在修改传递给堆栈的参数。 我还查找了包括System V i386调用约定的文档,但无法find明确的答案。

这是我正在debugging的一些示例代码

pushl %eax # %eax = 0x28 call _print_any popl %eax # %eax is Now 0x0a

我会假设GCC修改堆栈上的参数是好的,但我想知道它在哪里指定它可以这样做。

为什么即使callback参数与XML中的callback参数不匹配,GObject方法仍然会被调用

难道是在Windows重启pipe理器callbackAPI中有一个错误

在哪里,为什么,是应该指向的x64帧指针? (Windows x64 ABI)

Win VS2008调用约定:c

AVX寄存器如何由通用调用约定来处理?

Windows32 API:“mov edi,edi”在函数入口?

__stdcall没有任何装饰

我可以使用一个寄存器作为循环计数器吗?

理解x86-64函数前导码时遇到困难

为什么微软selectstdcall作为他们的API约定?

尽管调用者(在某些调用约定中)是清理参数的调用者,但实际上所做的只是释放先前在堆栈上分配的空间以保存参数值。 被调用者在函数执行期间可以自由修改这些值,因为调用者以后不会再查看它们的值。

在你发布的例子中,GCC发出了popl %eax指令来释放堆栈中参数占用的空间。 所有它真正需要做的就是将%esp(x86上的堆栈在内存中向下增长)添加4,并执行popl %eax指令是执行此操作的最短和最快的方法。 如果编译器需要释放20个值,它可能会直接修改%esp而不是发出20个popl指令。

您可能会发现下面的代码中没有使用%eax的新值。

是的,被调用者可以修改栈上的参数。 就被调用者而言,它们与局部变量相同。 调用者清理它们,但忽略了这个值。

如果你正在谈论C或C ++ POD,清理就是修改堆栈指针。

如果你用析构函数来谈论C ++,调用者负责调用析构函数,但是需要写入泛型类的析构函数来清除任何值。

在标准C中,被调用者可以修改其所有参数的值,但调用者永远不会看到更改。

可能会令人困惑的是,如果将POINTER传递给某个值,则被调用者可以通过解引用指针来更改该值,但是如果被调用者实际上更改指针本身,调用者将看不到该更改。

一个小的nit:C标准并不要求这个实现甚至有一个堆栈。

如果你通过价值:

call do_it(to_it);

该参数被复制(可能是堆栈的开始,但可能不取决于你的编译器)单元格的程序可以混淆这个副本尽可能多的,但在clling程序中的变量将不会改变。

如果你通过引用传递:

call do_it(&to_it);

然后传递变量的地址 。 被调用的变量所做的任何修改都将是调用程序中的原始变量。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐