在 Zed 的流行(观点)系列中,在“堆和堆栈”一章中,数据库的代码如下
请注意这是 Zed Shaw 的代码
struct Address {
int id;
int set;
char name[MAX_DATA];
char email[MAX_DATA];
};
struct Database {
struct Address rows[MAX_ROWS];
};
struct Connection {
FILE *file;
struct Database *db;
};
struct Connection *Database_open(const char *filename, char mode)
{
struct Connection *conn = malloc(sizeof(struct Connection));
if(!conn) die("Memory error");
conn->db = malloc(sizeof(struct Database));
if(!conn->db) die("Memory error");
if(mode == 'c') {
conn->file = fopen(filename, "w");
} else {
conn->file = fopen(filename, "r+");
if(conn->file) {
Database_load(conn);
}
}
if(!conn->file) die("Failed to open the file");
return conn;
}
void Database_create(struct Connection *conn)
{
int i = 0;
for(i = 0; i < MAX_ROWS; i++) {
// make a prototype to initialize it
struct Address addr = {.id = i, .set = 0};
// then just assign it
conn->db->rows[i] = addr;
}
}
我觉得在他的 Database_create 函数中,他调用了 struct Address 形式的分配内存,而内存 f 已经分配给 struct database 的创建,很奇怪。
然后我通过这种思路推断出他两次调用 malloc 的事实,首先为创建 Connection 分配堆内存,然后再为在 struct Connection(即 Databse)中创建 struct 类型应该很奇怪,因为好吧..我推断可能 Zed 知道并理解结构嵌套必须逐层构建。
就在此处发布问题之前,我决定编写一个简单的嵌套结构类型,并尝试通过一个 malloc 调用创建的最外层结构访问结构层内的数据....我的理由是,如果我认为没有需要逐层构造嵌套结构是真的,我可以访问嵌套数据而不会出现分段错误。我做到了
代码如下
#include<stdlib.h>
#include<stdio.h>
struct Killfly{
char str[20];
};
struct wtf
{
struct Killfly a;
};
struct wtf2{
struct wtf k;
};
int main(){
struct wtf2*fly=malloc(sizeof(struct wtf2));
printf("size of %ld \n",sizeof(*fly));
fly->k.a.str[0]='a';
//printf("size of wtf is %ld \n",sizeof(wtf));
free(fly);
return 0;
}
而且它写的没有段错误
问题
那么为什么 Zed 放置多个 malloc 调用,以及为什么当他已经为 struct Database 分配空间时,在函数 Database_struct 中,在 for 循环中,他继续调用基于堆栈的 struct Address 对象并将它们放置在所述类型的数组中?