2024-2025-1 20241407《计算机基础与程序设计》第十二周学习总结

作业信息

这个作业属于哪个课程 2024-2025-1计算机基础与程序设计
这个作业要求在哪里 2024-2025-1计算机基础与程序设计第十二周作业
这个作业的目标 学习指针与一维数组间的关系,与二维数组间的关系,向函数传递一维数组和二维数组,指针数组,命令行参数,动态数组,动态内存分配
作业正文 本博客

教材学习内容总结

《C语言程序设计》第五版第十一章的学习内容主要包括:

  1. 指针与一维数组间的关系
    • 探讨了指针如何用于访问和操作一维数组的元素。
    • 介绍了数组名作为指针使用的情况,以及如何通过指针遍历数组。
  2. 指针与二维数组间的关系
    • 讨论了二维数组的内存布局以及如何使用指针访问二维数组。
    • 介绍了指针算术在二维数组中的应用,以及如何通过指针操作二维数组的行和列。
  3. 向函数传递一维数组和二维数组
    • 讲解了如何将一维数组和二维数组作为参数传递给函数。
    • 讨论了在函数中如何使用指针来处理数组参数,以及数组参数在函数调用中的传递方式。
  4. 指针数组
    • 介绍了指针数组的概念,即数组的元素为指针。
    • 讨论了指针数组的声明、初始化和使用,以及它们在实际编程中的应用。
  5. 命令行参数
    • 讲解了如何在C语言程序中处理命令行参数。
    • 介绍了 main 函数的参数 argcargv,以及如何使用它们来访问命令行输入的参数。
  6. 动态数组
    • 讨论了动态数组的概念,即在程序运行时可以改变大小的数组。
    • 介绍了如何使用动态内存分配来创建和操作动态数组。
  7. 动态内存分配
    • 详细讲解了 malloccallocreallocfree 等函数的使用。
    • 讨论了动态内存分配的时机、内存泄漏问题以及如何管理动态分配的内存。
      这一章节的内容深入探讨了指针在C语言中的高级应用,特别是在处理数组和动态内存时的重要作用。通过学习这些内容,我们可以更好地理解指针的灵活性和强大功能,以及如何在实际编程中有效地使用它们。

教材学习中的问题和解决过程

问题一:malloc函数和calloc函数有什么区别?分别在哪种情况下,怎么使用?
解决方式:AI答:malloccalloc 都是C语言中用于动态内存分配的标准库函数,它们都属于C标准库中的 <stdlib.h> 头文件。尽管它们的目的都是为了分配内存,但它们在分配内存时的行为有所不同。

malloc 函数

  • 功能malloc 函数用于分配指定大小的内存块,但不会自动初始化内存。
  • 原型void* malloc(size_t size);
  • 参数size 表示要分配的字节数。
  • 返回值:返回一个指向分配的内存块的指针,如果分配失败,返回 NULL
  • 使用场景:当你需要分配一块内存,并且你打算立即用数据填充它,或者你不介意内存中的初始内容时,可以使用 malloc
    示例代码
#include <stdlib.h>

int main() {
    int *ptr = (int*)malloc(sizeof(int) * 10); // 分配一个可以存储10个int的内存块
    if (ptr == NULL) {
        // 处理内存分配失败
    } else {
        // 使用内存,例如赋值
        for (int i = 0; i < 10; i++) {
            ptr[i] = i;
        }
    }
    // 释放内存
    free(ptr);
    return 0;
}

calloc 函数

  • 功能calloc 函数用于分配指定数量和大小的内存块,并且会自动将分配的内存初始化为零。
  • 原型void* calloc(size_t num, size_t size);
  • 参数num 表示元素的数量,size 表示每个元素的大小(字节)。
  • 返回值:返回一个指向分配的内存块的指针,如果分配失败,返回 NULL
  • 使用场景:当你需要分配内存并希望内存中的所有位都被初始化为零时,可以使用 calloc。这在创建数组或结构体时特别有用,因为这样可以避免使用未初始化的内存。
    示例代码
#include <stdlib.h>
int main() {
    int *ptr = (int*)calloc(10, sizeof(int)); // 分配一个可以存储10个int的内存块,并初始化为0
    if (ptr == NULL) {
        // 处理内存分配失败
    } else {
        // 使用内存,内存已经被初始化为0
        for (int i = 0; i < 10; i++) {
            // ptr[i] 已经是0,可以直接使用
        }
    }
    // 释放内存
    free(ptr);
    return 0;
}

总结

  • 使用 malloc 当你不需要初始化内存,或者你将立即用数据覆盖内存中的值。
  • 使用 calloc 当你需要分配的内存被初始化为零,特别是当你创建数组或结构体并且希望所有成员都是零时。
    在任何情况下,使用完动态分配的内存后,都应该使用 free 函数释放内存,以避免内存泄漏。
    问题二:什么情况下需要动态内存分配?
    解决方式:AI答:动态内存分配是一种在程序运行时根据需要分配内存的技术。以下是一些需要动态内存分配的情况:
  1. 未知数据量
    • 当程序需要处理的数据量在编译时未知,或者数据量太大,无法使用静态分配(如固定大小的数组)时。
  2. 节省内存
    • 对于大型数据结构,如果它们不是一直被使用,可以使用动态内存分配来避免浪费内存空间。
  3. 灵活的数据结构
    • 当需要创建复杂或灵活的数据结构,如链表、树、图等,这些结构的大小和形状在编译时无法确定。
  4. 运行时决策
    • 根据用户的输入或其他运行时条件,程序可能需要分配不同大小的内存块。
  5. 对象池
    • 在需要频繁创建和销毁对象的场景下,使用动态内存分配可以减少创建和销毁的开销,尤其是在创建大量小对象时。
  6. 缓存
    • 当需要根据当前工作负载动态调整缓存大小时。
  7. 共享内存
    • 在多进程或多线程环境中,动态内存分配可以用来创建共享内存区域。
  8. 资源管理
    • 当需要管理有限的资源,如文件描述符或数据库连接时,动态分配可以根据当前需求调整资源数量。
  9. 避免栈溢出
    • 在递归或其他深度调用的场景下,动态分配可以帮助避免栈溢出。
  10. 扩展性
    • 对于需要良好扩展性的应用程序,动态内存分配可以根据系统资源和负载动态调整内存使用。
  11. 内存映射文件
    • 当需要处理大于物理内存的文件或数据集时,可以使用动态内存分配来映射文件的一部分到内存中。
  12. 优化性能
    • 在某些情况下,动态分配可以提高程序的性能,例如,通过减少内存复制或优化数据访问模式。
      动态内存分配提供了灵活性和控制,但也引入了额外的复杂性,如内存泄漏、野指针和内存碎片等问题。因此,在使用动态内存分配时,需要谨慎管理内存,确保及时释放不再使用的内存。
      问题三:指针数组怎么应用?
      解决方式:AI答:指针数组是数组的一种,其元素都是指针。这种数据结构在C语言中非常有用,因为它可以存储指向不同数据类型的指针,从而提供了很大的灵活性。以下是一些指针数组的应用场景:
  13. 字符串数组
    • 指针数组最常用的场景之一是存储字符串数组,即数组的每个元素都是一个指向字符数组(字符串)的指针。
    char* names[] = {"Alice", "Bob", "Charlie"};
    
  14. 函数指针数组
    • 用于存储指向不同函数的指针,可以实现基于函数的菜单或根据不同条件调用不同的函数。
    void (*functions[])(int) = {func1, func2, func3};
    
  15. 动态内存管理
    • 用于存储指向动态分配的内存块的指针,方便管理和释放内存。
    int* arrayPtrs[10];
    for (int i = 0; i < 10; ++i) {
        arrayPtrs[i] = malloc(sizeof(int) * 10);
    }
    
  16. 数据结构的实现
    • 在实现某些数据结构,如链表、树和图时,指针数组可以用来存储指向节点的指针。
  17. 参数传递
    • 传递多个字符串或对象给函数,而不是使用可变参数(...)。
    void processStrings(char** strings, int count) {
        for (int i = 0; i < count; ++i) {
            printf("%s\n", strings[i]);
        }
    }
    
  18. 资源数组
    • 在需要管理多种资源(如文件句柄、网络连接等)时,可以使用指针数组来存储这些资源的指针。
  19. 对象数组
    • 在创建对象数组时,可以使用指针数组来存储指向对象的指针,这样可以在不知道对象具体类型的情况下存储不同类型的对象。
  20. 二维数组的模拟
    • 在某些情况下,可以使用指针数组来模拟二维数组的行为,尤其是在二维数组的大小在编译时未知的情况下。
    int** matrix = malloc(rows * sizeof(int*));
    for (int i = 0; i < rows; ++i) {
        matrix[i] = malloc(cols * sizeof(int));
    }
    
  21. 命令行参数
    • main 函数的 argv 参数就是一个指针数组,它包含了命令行参数。
  22. 插件系统
    • 在设计插件系统时,可以使用指针数组来存储指向不同插件的指针。
      使用指针数组时,需要特别注意内存管理,确保为指针数组的每个元素分配的内存在使用完毕后都能被正确释放,以避免内存泄漏。同时,也要确保在使用指针数组之前,每个元素都已经被正确地初始化。

基于AI的学习

其他(感悟、思考等,可选)

学习了《C语言程序设计》第十一章之后,我有以下几点感悟:
1.我深刻体会到指针在C语言中的重要性和灵活性。指针不仅可以用于访问和操作数组,还可以用于动态内存管理、函数指针等多种高级应用。
2. 动态内存分配让我意识到程序设计中内存管理的重要性。正确地分配和释放内存对于编写高效、稳定的程序至关重要。
3. 通过指针数组和动态内存分配,我可以更深入地理解如何实现复杂的数据结构,如链表、树、图等,这些都是算法和系统设计的基础。
4. 学习了动态内存分配后,我开始思考如何优化代码,使其运行更快、更节省资源。
5. 我意识到,虽然动态内存分配提供了极大的灵活性,但也增加了程序设计的复杂性。需要仔细考虑内存泄漏、野指针等问题。
6. 在处理指针和内存时,每一个小错误都可能导致程序崩溃或不可预测的行为。这让我更加注重代码的细节和严谨性。
7. 通过实践,我更好地理解了之前学习的理论概念,如内存布局、栈与堆的区别等。
8. 学习了第十一章后,我对未来的学习内容充满期待,比如更高级的数据结构、算法、操作系统等。
9. 解决指针和内存管理中的难题会让我对编程有更深的热爱,享受编程带来的挑战和成就感。

学习进度条

代码行数(新增/累积) 博客量(新增/累积) 学习时间(新增/累积) 重要成长
目标 5000行 30篇 400小时
第一周 200/200 2/2 20/20
第二周 200/400 1/3 18/38
第三周 300/700 1/4 20/58
第四周 400/1100 1/5 22/80
第五周 300/1400 1/6 22/102
第六周 400/1800 1/7 25/127
第七周 400/2200 1/8 30/157
第八周 500/2700 1/9 35/192
第九周 500/3200 1/10 28/220
第十周 400/3600 1/11 30/250
第十一周 500/4100 1/12 30/280
第十二周 400/4500 1/13 30/310
posted @   王艺涵  阅读(13)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
点击右上角即可分享
微信分享提示