您的指针没有默认值。您的指针将指向它当前存储的任何内容。由于您尚未对其进行初始化,因此该行
newCell.subcells[i] = ...
有效地访问一些不确定的内存部分。请记住 subcells[i] 等价于
*(newCell.subcells + i)
如果左侧包含一些垃圾,您最终将添加i
一个垃圾值并访问该不确定位置的内存。正如您所说的,您必须初始化指针以指向某个有效的内存区域:
newCell.subcells = malloc(bytecount)
在哪一行之后,您可以访问那么多字节。关于其他内存来源,有不同类型的存储都有它们的用途。您获得哪种类型取决于您拥有哪种对象以及您告诉编译器使用哪种存储类。
malloc
返回一个指向没有类型的对象的指针。您可以使指针指向该内存区域,并且对象的类型将有效地成为指向对象类型的类型。内存未初始化为任何值,访问通常较慢。如此获得的对象称为allocated objects
。
- 您可以全局放置对象。他们的记忆将被初始化为零。对于点,您将获得 NULL 指针,对于浮点数,您也将获得适当的零。您可以依赖适当的初始值。
- 如果您有局部变量但使用
static
存储类说明符,那么您将具有与全局对象相同的初始值规则。内存的分配方式通常与全局对象相同,但这绝不是必要的。
- 如果你有没有任何存储类说明符或 with 的局部变量
auto
,那么你的变量将被分配到堆栈上(即使 C 没有这样定义,这当然是编译器实际上所做的)。您可以获取其地址,在这种情况下,编译器将不得不省略优化,例如将其放入寄存器中。
- 与存储类说明符一起使用的局部变量
register
被标记为具有特殊存储。结果,您无法再获取它的地址。在最近的编译器中,通常不需要再使用register
了,因为它们具有复杂的优化器。如果您真的是专家,那么如果使用它,您可能会从中获得一些性能。
对象具有相关的存储持续时间,可用于显示不同的初始化规则(正式地,它们仅定义对象至少存活多长时间)。声明为auto
并register
具有自动存储持续时间且未初始化的对象。如果您希望它们包含某些值,则必须显式初始化它们。如果不这样做,它们将包含编译器在它们开始生命周期之前留在堆栈中的任何内容。由malloc
(或该系列的另一个函数,如calloc
)分配的对象已分配存储持续时间。它们的存储也没有初始化。一个例外是使用时calloc
,在这种情况下,内存被初始化为零(“真正的”零。即所有字节 0x00,不考虑任何 NULL 指针表示)。static
使用和全局变量声明的对象具有静态存储持续时间。它们的存储被初始化为零适合它们各自的类型。请注意,对象不能有类型,但获得无类型对象的唯一方法是使用分配的存储空间。(C 中的对象是“存储区域”)。
那么什么是什么?这是固定代码。因为一旦你分配了一块内存,你就无法再找回你分配了多少项目,最好总是将这个计数存储在某个地方。我已经向dim
获取存储计数的结构引入了一个变量。
Cell makeCell(int dim) {
/* automatic storage duration => need to init manually */
Cell newCell;
/* note that in case dim is zero, we can either get NULL or a
* unique non-null value back from malloc. This depends on the
* implementation. */
newCell.subcells = malloc(dim * sizeof(*newCell.subcells));
newCell.dim = dim;
/* the following can be used as a check for an out-of-memory
* situation:
* if(newCell.subcells == NULL && dim > 0) ... */
for(int i = 0; i < dim; i++) {
newCell.subcells[i] = makeCell(dim - 1);
}
return newCell;
}
现在,dim=2 的情况如下所示:
Cell {
subcells => {
Cell {
subcells => {
Cell { subcells => {}, dim = 0 }
},
dim = 1
},
Cell {
subcells => {
Cell { subcells => {}, dim = 0 }
},
dim = 1
}
},
dim = 2
}
请注意,在 C 中,函数的返回值不需要是对象。根本不需要存储。因此,您不能更改它。例如,以下是不可能的:
makeCells(0).dim++
您将需要一个“免费功能”来再次释放分配的内存。因为分配对象的存储不会自动释放。您必须调用以释放树free
中每个指针的内存。subcells
把它写下来作为练习留给你:)