练习17:堆和栈的内存分配 笨办法学C

这是一个简单的数据库程序,它使用了堆上的动态内存分配来创建和管理数据库连接和数据。下面是关于堆和栈的一些说明,以及如何在代码中使用它们:

堆(Heap)上的内存分配:

在函数 Database_open 中,通过调用 malloc 分配了 struct Connectionstruct Database 的内存空间,这些内存空间位于堆上。
malloc 函数返回一个指向分配内存的指针,用于访问堆上的内存。
这些堆上的内存将在函数 Database_close 中通过调用 free 来释放,以避免内存泄漏。
栈(Stack)上的变量:

在 main 函数中,filename 和 action 是在栈上创建的变量。它们的值是通过命令行参数传递给程序的。
id 是另一个在栈上创建的变量,用于存储从命令行参数中解析的整数值。
堆和栈的区别:

堆和栈是内存中的两个不同区域,用于存储不同类型的数据。
堆上的内存分配和释放是手动控制的,需要显式地调用 malloc 和 free。堆上的内存生命周期由开发人员控制。
栈上的内存分配和释放是自动进行的,由编译器和运行时系统负责。栈上的内存生命周期与函数的调用关系密切相关。
堆上的内存可以动态增长,并且在程序运行期间保持有效。栈上的内存大小在编译时确定,一旦函数执行完毕,栈上的内存就会被自动释放。
堆上的内存需要手动管理,容易出现内存泄漏和悬挂指针等问题。栈上的内存由编译器和操作系统自动管理,通常更安全和高效。
总结起来,堆和栈是两个不同的内存区域,用于存储不同类型的数据。在程序中,可以使用堆上的动态内存分配来创建和管理复杂的数据结构,而栈上的变量用于存储临时的、局部的数据。
fopen 函数:

fopen 用于打开一个文件,并返回一个文件指针。
它接受两个参数:文件名和打开模式。打开模式可以是读取模式("r")、写入模式("w")、追加模式("a")等等。
如果文件成功打开,fopen 将返回一个指向该文件的文件指针,用于后续的文件操作。如果打开失败,它将返回 NULL。
fread 函数:

fread 用于从文件中读取数据。
它接受多个参数:要读取的数据存储位置的指针、每个数据项的大小、要读取的数据项数目、以及要读取的文件指针。
fread 从文件中读取指定数量的数据项,并将它们存储到指定的内存位置中。它返回实际读取的数据项数目。
fclose 函数:

fclose 用于关闭一个已打开的文件。
它接受一个文件指针作为参数,并将关闭文件。
在文件操作完成后,应该调用 fclose 来释放与文件相关的资源。
rewind 函数:

rewind 用于将文件指针重置到文件的开头。
它接受一个文件指针作为参数,并将文件指针设置为文件的起始位置。
rewind 在重新访问文件之前将文件指针重置到起始位置,以便从文件的开头重新读取数据。
这些文件操作函数用于处理文件的打开、读取、写入和关闭操作。它们为程序提供了与外部文件的交互能力,可以读取文件中的数据、写入数据到文件中,并在操作完成后关闭文件。这些函数是 C 语言标准库中提供的常用文件操作函数。
atoi 是 C 标准库中的一个函数,用于将字符串转换为整数类型。它的函数原型如下:

int atoi(const char *str);
str 是一个指向以 null 结尾的字符串的指针,表示待转换的字符串。
atoi 函数会尝试将 str 字符串解析为一个整数,并返回相应的整数值。如果无法解析整数,或者 str 指向的字符串为空或不是有效的整数表示形式,则 atoi 返回 0。

类似的函数还有:

atol:将字符串转换为长整型(long)。
atoll:将字符串转换为长长整型(long long)。
strtod:将字符串转换为双精度浮点数(double)。
strtof:将字符串转换为单精度浮点数(float)。
strtol:将字符串转换为长整型,并可指定进制。
strtoll:将字符串转换为长长整型,并可指定进制。
strtoul:将字符串转换为无符号长整型,并可指定进制。
strtoull:将字符串转换为无符号长长整型,并可指定进制。
这些函数提供了字符串到数值类型的转换功能,可以根据需要选择合适的函数来进行转换。
  • die函数需要接收conn变量作为参数,以便执行清理并关闭它
void die(struct Connection *conn, const char *message)
{
    if(errno) {
        perror(message);
    } else {
        printf("ERROR: %s\n", message);
    }

    if (conn) {
        Database_close(conn);
    }

    exit(1);
}
$ make ex17
cc -Wall -g    ex17.c   -o ex17
ex17.c: In function ‘die’:
ex17.c:24:9: warning: implicit declaration of function ‘Database_close’ [-Wimplicit-function-declaration]
   24 |         Database_close(conn);
      |         ^~~~~~~~~~~~~~
ex17.c: At top level:
ex17.c:60:6: warning: conflicting types for ‘Database_close’; have ‘void(struct Connection *)60 | void Database_close(struct Connection *conn)
      |      ^~~~~~~~~~~~~~
ex17.c:24:9: note: previous implicit declaration of ‘Database_close’ with type ‘void(struct Connection *)24 |         Database_close(conn);
      |         ^~~~~~~~~~~~~~

这个问题是由于C语言的函数声明顺序导致的。在C语言中,如果你在调用一个函数之前没有声明它,编译器会假设这个函数的返回类型是int,并且没有参数。这就是为什么你在die函数中看到了关于Database_close的警告。

为了解决这个问题,你需要在die函数之前声明Database_close函数。

  • 修改代码,使其接收参数作为MAX_DATA和MAX_ROWS,将它们储存在Database结构体中,并且将它们写到文件。这样就可以创建任意大小的数据库。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

weixin_44781508

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值