C是否需要堆栈和堆才能运行?

C是否需要堆栈和堆才能运行?,c,heap-memory,stack-memory,C,Heap Memory,Stack Memory,人们谈论堆栈和堆是什么以及它们之间的区别。但我很想知道,如果CPU不支持堆栈和堆结构,那么C在没有堆栈和堆的情况下能否正常运行?C语言需要(正如chqrlie指出的)某种机制来实现自动存储并跟踪函数调用返回点。实际上,这总是一堆。但它不需要堆 只有在使用库函数(如malloc)时才使用堆;而不是C语言本身。堆实际上没有什么神奇之处——你可以用纯C编写malloc和free。它只是有一大块静态内存,并有一个从块中分配空间的算法 您会问“如果CPU不支持堆栈和堆结构”怎么办? 堆栈和堆只是由内存和指

人们谈论堆栈和堆是什么以及它们之间的区别。但我很想知道,如果CPU不支持堆栈和堆结构,那么C在没有堆栈和堆的情况下能否正常运行?

C语言需要(正如chqrlie指出的)某种机制来实现自动存储并跟踪函数调用返回点。实际上,这总是一堆。但它不需要堆

只有在使用库函数(如
malloc
)时才使用堆;而不是C语言本身。堆实际上没有什么神奇之处——你可以用纯C编写
malloc
free
。它只是有一大块
静态
内存,并有一个从块中分配空间的算法

您会问“如果CPU不支持堆栈和堆结构”怎么办?
堆栈和堆只是由内存和指针组成的。我不认为你会发现一个可以被视为“CPU”的处理器没有这种能力的例子。

不,它没有。让我们先讨论一下,这很容易

不提供任何类型堆的实现只要在尝试调用
malloc
(或任何其他内存分配函数)时返回
NULL
。根据标准,这是完全可以接受的行为


就堆栈而言,它也不需要提供堆栈。ISO C11完全零次提到“堆栈”一词

实现所需要做的只是成为标准中指定的所有内容的正确“虚拟机”。当然,如果没有堆栈,这将是非常困难的,但这不是不可能的。作为一种极端情况,没有任何东西表明不能简单地递归地内联每个函数调用。这将使用大量的代码和特定于函数的数据空间,但这肯定是可行的

然而,这可能会说服我转移到另一个架构,一个确实有堆栈(和堆)的架构


话虽如此,即使体系结构既不提供堆也不提供堆栈,这两种都可以通过基本内存I/O操作构建。事实上,我十几岁时拥有的最早的电脑中有一台装有RCA 1802 CPU,它没有专用的堆栈。它甚至没有
调用
ret
指令

然而,它可以使用其SCRT(标准调用和返回技术)很好地处理子例程和堆栈(对于单词“well”的某些定义)。有关这个美丽的东西(或怪物,取决于你的观点)是如何工作的,以及其他一些不寻常的架构,请参阅


IBMz(又称Systemz,zSeries,不管他们本周怎么称呼它)实际上有一个堆(可以从操作系统中分配内存),但没有堆栈。它实际上通过使用此堆内存和某些寄存器(类似于上面链接中引用的RCA芯片)来实现链表堆栈,这意味着函数prolog使用
STORAGE-get
分配本地函数内存,epilog使用
STORAGE-RELEASE
释放它


不用说,这会为每个函数在prolog和epilog中添加相当多的额外代码。

正如其他答案所解释的,C11标准既不需要堆栈也不需要堆(请参阅)。但是,在实践中,两者都是有用的

关于这一点,这是很常见的,但可以“避免”:

  • 有些可能足够聪明(特别是对于整个程序优化或链接时优化),可以检测到整个程序不需要任何的情况(一个简单的情况是整个程序没有函数指针,没有递归:在这种情况下,每个“调用帧”都可以在编译时静态分配)。许多优化编译器都是一些调用(有效地消除了这些调用对调用堆栈的需求),甚至对于未标记为
    inline
    的函数也是如此

  • 今天的许多处理器(或,即…)都有一个硬件调用堆栈(例如,一些“”称为函数调用)。对于那些没有这样的硬件堆栈指针的设备(例如大型机、或),通常(或)可能会专用一些寄存器来充当堆栈指针的角色。顺便说一句,C甚至可以在理论上为(没有任何寄存器或堆栈指针的)实现

  • 可以想象编译器使用来避免调用堆栈(有效地在堆中或堆中“分配”一些“调用帧”,可能需要一些人的帮助)。阿佩尔的旧书详细解释了这一观点。我不能说出任何C编译器的名字,但是标准允许这种方法。如果您将一些编译器从C编码到SML(或某些Lisp),您就可以拥有这样一个编译器

关于C堆,
malloc
函数可能总是失败,这仍然符合标准,但可能是最快的。此外,C标准允许独立实现完全没有任何
malloc

如果你寻找一个C语言几乎需要的特性,我会研究二进制表示法。我倾向于认为,为十进制计算机(如旧计算机)或三元计算机(如)实现C11编译器是非常不切实际的(但原则上是可能的,因为您可以“在三元或十进制计算机上实现二进制计算机;都是这样的”)。然而,你只能在博物馆里找到这样的旧电脑(20世纪50年代末、60年代初),它们在C语言发明之前就消失了

顺便说一句,和(和)实现中存在调用堆栈和堆,比C早了几十年。

问“我从哪里开始”的问题通常太广泛,不适合此站点。人们有自己的解决问题的方法,因此不可能有正确的答案。那就好好读一读吧