gpt4 book ai didi

c - 函数内是否可以获取由返回值初始化的变量的内存地址?

转载 作者:行者123 更新时间:2023-12-02 09:06:09 25 4
gpt4 key购买 nike

我一直在研究 C 中的内联汇编以及调用堆栈的工作原理,但我一直无法弄清楚是否可以检索请求函数返回值的变量的地址,从函数内部。

int hypothetical_func(){

/*...
.. some assembly to get the address of 'int a' from the call stack?
...*/

return 5;
}

int main(){
int a = hypothetical_func();
}

这可能吗?

最佳答案

不。 int在寄存器中返回,并且被调用者不参与调用者在返回后对该寄存器执行的操作。它可能永远不会存储在内存中。

如果返回类型不是int ,而是足够大的值,调用约定按值返回它,然后 hypothetical_func将有一个输出地址。 (或者假设的(可怕的)调用约定可能会通过隐藏指针而不是寄存器返回 int。假设机器是像所有真实 CPU 一样的寄存器机器。)

但这可能只是一个临时返回值,而不是赋值的实际 LHS。(或者初始化,这与 C(如果不是 C++)中的相同内容足够接近)。特别是当分配给全局或其他东西时。请参阅What prevents the usage of a function argument as hidden pointer?对于 *out = foo(); 的情况哪里T *out是一个函数arg。证明是否/何时可以安全地将函数 arg 作为 foo() 的返回值对象传递是非常重要的。 .

有些编译器甚至不尝试优化,只是在堆栈上为返回值临时腾出空间,然后从那里复制到最终对象中。

正如 @prl 指出的那样,返回值甚至可能不是变量的初始值设定项。例如printf("%d\n", foo());只是将返回值传递给函数 arg。 或者foo();丢弃返回值,而不将其分配到任何地方。(但是,如果调用约定指定函数通过隐藏指针返回,则调用者必须将指针传递给足够的暂存空间。被调用者是仍然会写入它的返回值,并且不需要从坏指针中出现段错误或覆盖其他内容。这是与 C 抽象机的操作分开的 asm/调用约定细节。或者我猜你可以说返回值对象仍然存在,只是没有分配到任何地方。)


加上内联汇编,您甚至无权访问它。除非你算写一个__attribute__((naked))函数,您仍然在 asm 语句中编写整个函数,并且编译器除了函数名称的名称修饰之外不处理任何内容。没有序言或尾声,或者使用 args 的 C 变量和您所使用的 C 变量来抽象调用约定 return 。 (/提示 C 编译器无法创建在多个寄存器中返回多个单独值的函数,就像在手写汇编中一样。)

但即使使用手写的汇编语言,对于 x86 和 ARM 等普通 ISA 上的普通调用约定也无法做到这一点。 int 的返回值对象只是一个寄存器。

关于c - 函数内是否可以获取由返回值初始化的变量的内存地址?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58218953/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com