我可以将数据推送/弹出到GCC C返回堆栈吗?

时间:2015-11-13 20:20:22

标签: c gcc stack

在GCC C中,有没有办法将数据推送/弹出到C返回堆栈?

我不是在谈论实现我自己的堆栈(我知道如何做到这一点);我的意思是使用现有的C返回堆栈来显式地推送/弹出参数(当然,在同一级别的大括号​​内)。

例如:

extern int bar;

void foo(void) {
  PUSH(bar);

  bar = 12;
  doSomething(); // that depends on the value of bar

  bar = POP();   // restore original value of bar
}

如果有任何简单的方法可以做到这一点,我认为使用像#34; oldBar"这样的局部变量将是一个更干净的选择。明确。

3 个答案:

答案 0 :(得分:8)

如果使用临时变量,它基本上是相同的。临时变量在堆栈上分配或优化到寄存器。

e.g。

extern int bar;

void foo(void) {
  int tmp = bar
  bar = 12;
  doSomething(); // that depends on the value of bar
  bar = tmp;   // restore original value of bar
}

显然,C实际上并不需要将堆栈结构用于调用,因此这种功能没有意义。这是在本文的内存布局部分https://www.seebs.net/c/c_tcn4e.html

中声明的
  

很简单,并非每个编译器都有“堆栈”。有些系统实际上没有任何此类功能。 C的每个编译器都有某种处理函数调用的机制,但这并不意味着它是一个堆栈。更重要的是,功能参数或局部变量通常不存储在任何“堆栈”中,而是存储在CPU寄存器中。这种区别可能很重要,而且应该被覆盖,而不是手工挥手。

从技术上讲,您也可以使用alloca()(位于alloca.h中)来执行此操作,但释放该内存的唯一方法是返回函数调用。它也没有真正做你所建议的。 alloca不是C标准的一部分

答案 1 :(得分:0)

如果您使用纯C编写,则可以使用可变参数函数。当然,这不是一个完整的解决方案,因为只有在调用函数时才会在函数调用和参数被推送后清除堆栈。 但如果您需要按照您的描述使用它,它可能会起作用:

extern int bar;
void doSomething(...);
void foo(void) {
  doSomething(&bar);
  //you do not need here to pop to restore the bar value, as you push a copy of value
}

如果你想在推送后做一些其他动作(我甚至无法想象),你可以使用包装函数。

extern int bar;
void doSomething();
void doSomethingWrapper(...) {
   //here arguments that are passed in ... are pushed
   doSomething();
   //and here they are poped
}
void foo(void) {
  //....
  doSomethingWrapper(&bar);
  //....
}

如果您只想以巧妙的方式操作堆栈,唯一的解决方案是使用内联汇编。或者您可以调用函数void push(...)来推送您想要的任何内容,并在longjmp()的主体中使用push(),以避免在控制流离开函数时弹出参数。

答案 2 :(得分:0)

好的,这就是我想要的:

#define PUSHINT(var) int old__##var = var
#define POPINT(var) var = old__##var

extern int bar;

void foo(void) {
  PUSHINT(bar);

  bar = 12;
  doSomething(); // that depends on the value of bar

  POPINT(bar);   // restore original value of bar
}

如果我能保证“old__”前缀每次都是唯一的,那会更好,但我不知道该怎么做(这不太可能是一个问题)。

它也没有真正做到PUSH / POP(尽管它确实存储在返回堆栈上,至少在我的硬件上)。您不能推送一个值并弹出另一个值。

但我首先不想这样做。

我可以将宏重命名为SAVE()和RESTORE()...

(感谢@ BobbySacamano的回答提示。)