从我对C的理解来看,似乎你应该使用malloc(size)每当你试图初始化,例如,数组的大小,你不知道直到运行时
但是我想知道为什么函数malloc()返回一个指针到变量的位置,为什么你甚至需要它。
基本上,为什么C不把这些都隐藏起来,这样当你做这样的事情时:
// 'n' gets stdin'ed from the user
...
int someArray[n];
for(int i = 0; i < n; i++)
someArray[i] = 5;
你可以做到这一点,而不必调用malloc()或其他一些函数?其他语言这样做吗(通过隐藏内存属性/位置)?我觉得作为一个初学者,处理变量的内存位置的整个过程只会让程序员感到困惑(因为其他语言不使用它,C似乎做了一个简单的初始化过程,比如这个过于复杂)…
基本上,我想问的是为什么malloc()甚至是必要的,因为为什么语言不能在没有程序员必须关心或必须看到内存的情况下在内部为你照顾所有这些。由于
*edit:好吧,也许有一些版本的C,我不知道,允许你放弃使用malloc(),但让我们试着忽略它现在…
C让你管理程序的每一个小细节。当内存被分配时,你可以管理;当被释放时,你可以管理;你可以管理如何增加一个小的分配,等等。
如果您不喜欢管理这些,而让编译器为您做,请使用另一种语言。
实际上C99允许这样做(所以您不是唯一一个想到它的人)。该特性被称为VLA(可变长度数组)。
读取int
,然后有一个大小的数组是合法的:
int n;
fscanf("%d", &n);
int array[n];
当然有限制,因为malloc
使用堆,VLA
使用堆栈(所以vla不能像malloc
ed对象那么大)。
*edit:好吧,也许有一些版本的C,我不知道,允许你放弃使用malloc(),但让我们试着忽略
这样我们就可以集中精力在火焰上了
基本上,我想问的是为什么malloc()是必要的,因为为什么语言不能为你照顾所有这些在内部,程序员不必担心或必须看到内存
malloc()的关键,它的理由是être,它的函数,如果你愿意的话,是分配一块内存。在C语言中,我们引用内存块的方式是通过它的起始地址,根据定义,这是一个指针。
C已经有近40年的历史了,它并不像一些更现代的语言那样"高级"。有些语言,如Java,试图通过对程序员隐藏指针和显式内存管理来防止错误和简化编程。C不是那样的。为什么?因为事实并非如此。
基本上,我想问的是为什么malloc()甚至是必要的,因为为什么语言不能在没有程序员必须关心或必须看到内存的情况下为您内部照顾所有这些。由于
C语言的特点之一是它的简单性(C语言编译器相对容易实现);使语言变得简单的一种方法是强迫程序员自己完成所有的内存管理。显然,其他语言为你管理堆上的对象——Java和c#是现代的例子,但这个概念一点也不新鲜;Lisp实现已经做了几十年了。但是这种便利是以编译器复杂性和运行时性能为代价的。
Java/c#方法有助于消除C特有的整个类的内存管理错误(内存泄漏,无效指针解引用等)。出于同样的原因,C提供了对内存管理的控制级别,允许程序员实现在其他语言中很难(并非不可能)达到的高水平性能。
如果动态分配的唯一目的是分配可变长度数组,那么malloc()
可能就没有必要了。(但请注意,malloc()
早在变长数组被添加到语言之前就存在了。)
但是VLA的大小在对象创建时是固定的(在运行时)。它不能调整大小,而且只有当您离开声明它的作用域时,它才会被释放。(vla,不像malloc()
,没有报告分配失败的机制。)
malloc()
给你一个很多更大的灵活性。
考虑创建一个链表。每个节点都是一个结构,包含一些数据和指向列表中下一个节点的指针。您可能提前知道每个节点的大小,但不知道要分配多少个节点。例如,您可以从文本文件中读取行,为每行创建并追加一个新节点。
您还可以使用malloc()
和realloc()
来创建缓冲区(例如,unsigned char
的数组),其大小可以在创建后更改。
是的,有一些语言不公开指针,它们为你处理内存管理。
它们中的很多都是用c实现的
也许问题应该是"当你可以使用指针时,为什么你需要像int array[n]
这样的东西?"
毕竟,指针允许你在它被创建的范围之外保持对象的活动,你可以使用指针来切片和切片数组(例如strchr()
返回一个指向字符串的指针),指针是轻量级对象,所以传递给函数和从函数返回它们是很便宜的,等等。
但真正的答案是"就是这样"。其他选项是可能的,而且证据是有其他语言可以做其他事情(甚至C99也允许不同的事情)。
C被视为高度发达的低级语言,malloc主要用于动态数组中,动态数组是栈中的关键组件&队列中。对于其他隐藏指针部分的语言,开发人员不能很好地进行与硬件相关的编程。
对您的问题的简短回答是思考这个问题:如果您还需要精确地控制何时解除内存分配,该怎么办?
C是编译语言,不是解释语言。如果你不知道n
在编译时,编译器应该如何产生一个二进制文件?