你能在堆栈上定义一个数组并将指针传递给全局变量吗?

时间:2013-11-21 03:53:12

标签: c arrays memory stack global

我在不支持任何内存分配命令的微芯片上编程C,但它确实喜欢指针(当然)。所以我的问题是:

有没有办法在函数中定义数组,并将指向该数组的指针传递回全局变量?

这将是一种在没有malloc,realloc或calloc的情况下使用动态内存的方法。基本上堆栈内存被传递回全局而不会破坏它自己。我假设特别需要alloc命令来确保它不被破坏,但我想检查一下是否有解决方法。

7 个答案:

答案 0 :(得分:2)

  1. 是的,您可以在函数中声明数组。数组的内存将在调用堆栈上 - 尽管小心,没有malloc通常伴随着一个小堆栈。
  2. 是的,您可以将本地声明的数组的地址提供给全局声明的指针。
  3. 是的,在某些情况下,它可以是动态内存的便利来源,但无论您是声明本地数组还是调用备受mal alloca函数,结果都是相同的。
  4. 但是,在从数组所在的函数返回之前,内存才是安全的,因此您无法将其转换为malloc样式,而只是为您的调用子项生成内存/暂存。

答案 1 :(得分:2)

您需要定义一个巨大的全局数组来保留大块内存然后使用该数组。如果您愿意,还可以编写一些简单的alloc / free函数来分配/释放该数组中的块。

下一个函数调用将重用堆栈内存。因此,在函数返回后,您无法保留任何内容。当然,如果你知道在使用该变量时你的函数不会返回(例如,main函数的局部变量),那么将指针传递给该变量是安全的。

答案 2 :(得分:1)

你的意思是这样吗?

char* x;
int main(int argc, char** argv) {
  static char foo[80];
  x = foo;

  // ...
}

这会将您的缓冲区放入BSS段。如果您希望它保留在运行时堆栈上,请删除static

foo有自动存储(基本上,它的大小是固定的),但你现在有一个全局可见的指针。 它将一直持续到main返回,这可能是你的过程的结束,你不再需要了它。

如果你想拥有真正的动态内存,你必须按照评论中的建议编写自己的内存分配器。

答案 3 :(得分:1)

您可以在函数中将数组定义为静态,并将值赋给全局指针。不确定我会称这是一个很好的编程习惯。

请注意,这只会获得一个数组副本,因此对函数的后续调用不会创建数组的其他实例。在这种情况下,我会问你为什么不首先将数组设为全局?

答案 4 :(得分:1)

可以在全局变量中存储具有自动存储持续时间(您的数组“在堆栈中”)的对象的地址,但这不会以任何方式增加对象的生命周期。当执行声明结束的块时,它仍然不存在。在它不再存在之后,进一步使用存储在全局变量中的指针将导致未定义的行为。

答案 5 :(得分:1)

主要问题是函数调用以及调用如何影响堆栈。在IBM体系结构上,简单地说,当前EBP被推送到堆栈,调用者堆栈帧被保存到EBP并且被调用者参数被推送到堆栈(通常)。在返回时,推送的EBP被激活,并且调用者可以覆盖堆栈分配的参数,因为返回被调用者,该区域可以自由使用。

当你在堆栈上动态分配一些空间时,它有可能在函数调用的某个时间覆盖该空间,该函数调用具有一些广泛的参数或递归调用。这就是为什么所有动态分配都在堆中发生,并且堆管理由操作系统完成。因为malloc(等)是o.s.用于堆分配的包装器,您无需担心该管理,o。会照顾你。

如果要在堆栈上实现动态分配,则需要使用汇编。确保在调用者站点的函数调用之前分配足够的空间,并在调用者返回其调用者时占用该空间。而且我猜这个组织会是一个脑力劳动......

答案 6 :(得分:0)

在“堆栈”上分配内存的简单方法,将其地址传递给全局内存。

这样做的一个潜在原因是创建一个“状态”(数据集),但不必将其传递给子函数,因为嵌套可能非常深,可能会有堆栈节省。多线程应用程序中的价格无法安全使用Function()

请注意,调用Function()的任何内容都不应使用State

static char *State;

static int FunctionFoo_Helper(void) {
  if (*State != '\0') {
    // Do _something_ more interesting than simply print
    printf("%c", *State++);
    FunctionFoo_Helper();
  }
}

void Function(size_t n) {
  char Array[n];  // Variable size array
   // As to if the system put this on the stack or elsewhere is system dependent.

  Populate Array(Array);
  Array[n-1] = '\0';
  State = Array;
  FunctionFoo_Helper();
}