我正在做嵌入式编程,其中节省内存很重要。
以下 C 代码在运行时会占用多少堆栈空间?
if (send_small_message) {
uint8_t buffer[16000];
// do something with the buffer
} else {
uint8_t buffer[32000];
// do something the with buffer
}
Run Code Online (Sandbox Code Playgroud)
某些编译器能否决定为两个缓冲区分配 16000 + 32000 = 48kB 堆栈空间?或者是否保证因为两个缓冲区永远不会同时使用,编译器将只分配 32kB - 较大缓冲区的大小?
跟进问题:
void SendSmallMessage() {
uint8_t buffer[16000];
// do something with the buffer
}
void SendLargeMessage() {
uint8_t buffer[32000];
// do something with the buffer
}
Run Code Online (Sandbox Code Playgroud)
某些编译器编译的代码是否可以在运行时使用 16000 + 32000 字节来执行以下代码段:
if (send_small_message) {
SendSmallMessage();
} else {
SendLargeMessage();
}
Run Code Online (Sandbox Code Playgroud)
Lun*_*din 11
C 标准是否保证使用的堆栈数量?
对此不存在任何保证。C 标准没有提到像栈这样的概念。您甚至可以为完全没有堆栈的低级 CPU 编写 C。
然而,C 标准确实保证uint8_t在您的系统上是 1 个字节大并且 1 个字节是 8 位(否则uint8_t将不可用)。
以下 C 代码在运行时会占用多少堆栈空间?
某些编译器能否决定为两个缓冲区分配 16000 + 32000 = 48kB 堆栈空间?
特定于系统,但也取决于函数的编写方式和发生的优化。但是,一般来说,在给定所有可能的执行路径的情况下,现实世界的系统为函数所需的堆栈分配空间。所以很可能许多编译器会分配 16k + 32k。
但谁在乎呢,因为在任何已知系统的堆栈上分配大量内存都没有意义。不是在高端的类似 PC 的系统上,当然也不是在内存受限的嵌入式系统上。你会到处都是堆栈溢出。
嵌入式中的一般经验法则是永远不要在堆栈上分配任何形式的缓冲区,而是始终具有静态存储持续时间。在类似 PC 的系统上,堆分配是另一种选择。
@Lundin 提供了一个很好的答案。但我想从稍微不同的角度来回答。
C 标准基本上保证了代码的行为。它并不能保证它是如何完成的。它甚至有可能(不知道有多大可能)将缓冲区声明移到 if 语句之外。它也可能分配比指定更多的内存。如果它不破坏任何东西,也允许分配更少。通常,优化器会删除未使用的变量。优化器还经常内联小函数而不是调用它们,并且它可能将 a 更改printf("\n")为 a puts("")。只要代码的可观察行为保持不变,编译器就可以自由地做任何事情。
所以不,在这种情况下你没有任何保证。
但这里要考虑一件事。您想根据 if 语句声明不同大小的缓冲区。假设这些额外的 16kB 会引起堆栈溢出。如果剩余的堆栈少于 32kB 并且需要执行 else 分支,您会怎么做?当然这取决于代码在现实中的使用方式,但绝对值得考虑。对我来说,这是一种非常强烈的代码味道。