2024-2025-1 学号:20241301 《计算机基础与程序设计》第九周学习总结

news/2025/2/24 16:23:55/文章来源:https://www.cnblogs.com/HonJo/p/18566259

|这个作业属于哪个课程|2024-2025-1-计算机基础与程序设计|
|这个作业要求在哪里|2024-2025-1计算机基础与程序设计第一周作业|
|这个作业的目标|<复习知识,巩固基础>|
|作业正文|https://www.cnblogs.com/HonJo/p/18566259|

一、教材学习内容总结
(一)指针与数组
在C语言中,指针和数组有着密切的关系。理解它们之间的关系对于有效地使用C语言至关重要。以下是指针与数组之间的一些关键联系:

1. 数组名作为指针

在C语言中,数组名可以被用作指向数组第一个元素的指针。当你有一个数组时,如 int arr[10];arr 本身就是一个常量指针,指向数组的第一个元素。这意味着 arr&arr[0] 是等价的。

2. 通过指针访问数组元素

你可以使用指针运算来访问数组中的元素。如果你有一个指向数组第一个元素的指针 int *p = arr;,那么你可以通过 p[i] 来访问数组的第 i 个元素,这与 arr[i] 是等价的。

3. 指针和数组的遍历

在遍历数组时,你可以使用一个指针来逐个移动到数组的每个元素。例如:

int arr[] = {1, 2, 3, 4, 5};
int *p = arr;
for (int i = 0; i < 5; i++) {printf("%d ", *(p + i)); // 等价于 printf("%d ", arr[i]);
}

4. 指针和数组的内存布局

数组在内存中是连续存储的,这意味着你可以使用指针运算来移动到下一个元素。p + i 实际上是将指针 p 向前移动 i 个元素的大小。

5. 传递数组到函数

当你将数组传递给函数时,实际上传递的是指向数组第一个元素的指针。因此,函数接收到的是数组的指针副本,任何对数组元素的修改都会反映到原始数组上。

void func(int arr[]) {// 这里的 arr 实际上是一个指向数组第一个元素的指针
}int main() {int myArray[10];func(myArray); // 传递 myArray 实际上是传递 &myArray[0]return 0;
}

6. 指针数组和数组指针

  • 指针数组:一个包含指针的数组,例如 int *arr[10];
  • 数组指针:一个指向数组的指针,例如 int (**arr)[10];

7. 多维数组和指针

对于多维数组,每一维都可以看作是指针。例如,对于 int arr[10][5];arr 是一个指向包含5个整数的数组的指针,arr[i] 是一个指向整数的指针。

8. 指针和数组的安全性

使用指针访问数组时,必须小心不要越界,因为这会导致未定义行为,可能引发程序崩溃或数据损坏。

理解指针和数组之间的关系对于高效、灵活地操作数组至关重要,也是理解更高级的内存操作和数据结构(如链表、树等)的基础。

(二)函数指针
函数指针是指向函数的指针,它存储了一个函数的地址。在C语言中,函数也被视为内存中的对象,因此它们有自己的地址。函数指针可以被用来存储函数的地址,并且可以像使用普通指针一样使用它们来调用函数。

函数指针的声明

声明一个函数指针时,需要指定指针指向的函数的返回类型和参数类型。语法如下:

返回类型 (*指针名称)(参数类型列表);

例如,假设有一个返回 int 并接受两个 int 参数的函数,声明一个指向这种函数的指针如下:

int (*funcPtr)(int, int);

函数指针的初始化

你可以将函数指针初始化为指向一个具体的函数:

int add(int a, int b) {return a + b;
}int (*funcPtr)(int, int) = add; // 将函数指针指向 add 函数

调用函数指针

通过函数指针调用函数与直接调用函数类似,只需要在函数指针后加上括号和参数:

int result = funcPtr(5, 10); // 调用 add 函数

函数指针作为参数

函数指针经常作为参数传递给其他函数,这允许在运行时决定调用哪个函数。例如,你可以编写一个函数,它根据传入的函数指针来处理不同的操作:

void applyFunction(int a, int b, int (*func)(int, int)) {int result = func(a, b);printf("Result: %d\n", result);
}int main() {applyFunction(3, 4, add); // 传递 add 函数return 0;
}

函数指针数组

你也可以创建函数指针数组,这允许你根据索引来选择不同的函数:

int (*funcArray[5])(int, int) = {add, subtract, multiply, divide, modulo};// 调用数组中的函数
int result = funcArray[0](10, 5); // 调用 add 函数

注意事项

  • 确保函数指针指向的函数的签名(参数类型和返回类型)与函数指针声明时的签名匹配。
  • 未初始化的函数指针是危险的,因为它们可能指向任意内存地址,使用未初始化的函数指针调用函数会导致未定义行为。
  • 函数指针可以用来实现回调函数,策略模式等高级编程技巧。

函数指针是C语言中一个强大的特性,它提供了函数级别的抽象和灵活性。在C语言库中,特别是在信号处理和回调函数中,函数指针被广泛使用。

(三)内存分配
在C语言中,内存分配主要分为两类:栈内存分配和堆内存分配。

栈内存分配(自动内存分配)

栈内存分配是自动的,通常用于局部变量的存储。当函数被调用时,其局部变量的存储空间会自动在栈上分配。当函数返回时,这些局部变量的存储空间会自动释放。

int func() {int localVar = 10; // 栈内存自动分配// 使用 localVarreturn localVar;
}

堆内存分配(动态内存分配)

堆内存分配是手动的,通常使用 malloccallocreallocfree 函数来管理。

  • malloc:分配指定大小的内存块,返回指向它的指针。
  • calloc:分配指定数量的元素,每个元素指定大小的内存块,并将它们初始化为0。
  • realloc:重新分配内存块的大小,可以增加或减少。
  • free:释放之前分配的内存。

使用 mallocfree

#include <stdlib.h>int *allocateMemory() {int *ptr = (int *)malloc(sizeof(int) * 10); // 分配一个可以存储10个int的内存块if (ptr == NULL) {// 处理内存分配失败}// 使用内存free(ptr); // 释放内存return ptr;
}

使用 callocfree

#include <stdlib.h>int *allocateMemory() {int *ptr = (int *)calloc(10, sizeof(int)); // 分配10个int的内存块,并初始化为0if (ptr == NULL) {// 处理内存分配失败}// 使用内存free(ptr); // 释放内存return ptr;
}

注意事项

  • 检查 malloccallocrealloc 的返回值是否为 NULL,以确保内存分配成功。
  • 总是使用 free 释放使用 malloccallocrealloc 分配的内存,避免内存泄漏。
  • 避免多次释放同一块内存,这可能会导致未定义行为。
  • 堆内存分配和释放是编程中常见的错误来源,需要谨慎处理。

堆内存分配提供了更大的灵活性,允许程序在运行时根据需要分配和释放内存。这对于处理大小未知的数据或大量数据时非常有用。然而,这也意味着程序员需要更加小心地管理内存,以避免内存泄漏和其它内存相关的错误。

二、教材学习中遇到的问题
(一)只用指针遍历数组
在C语言中,使用指针遍历数组是一种常见的操作。你可以使用指针算术来遍历数组中的每一个元素。以下是如何使用指针遍历数组的步骤:

1. 定义数组和指针

首先,定义一个数组和一个指向数组第一个元素的指针。

int array[] = {10, 20, 30, 40, 50};
int *ptr = array; // 指针指向数组的第一个元素

2. 使用循环遍历数组

使用一个循环,通过指针递增来遍历数组中的每个元素。

for (int i = 0; i < sizeof(array) / sizeof(array[0]); i++) {printf("%d ", *ptr); // 打印当前指针指向的元素的值ptr++; // 将指针移动到下一个元素
}

在这个例子中,sizeof(array) / sizeof(array[0]) 计算数组中的元素数量。*ptr 是解引用操作符,它获取指针指向的元素的值。

3. 使用指针和循环变量

你也可以使用循环变量来控制指针的移动。

for (int i = 0; i < sizeof(array) / sizeof(array[0]); i++) {printf("%d ", array + i); // 打印当前索引处的元素的值
}

这里,array + i 是数组的第 i 个元素的地址,*(array + i) 将是该地址处的值。

4. 使用指针和循环变量(指针递增)

另一种常见的方法是直接在循环中递增指针。

for (int *ptr = array; ptr < array + sizeof(array) / sizeof(array[0]); ptr++) {printf("%d ", *ptr); // 打印当前指针指向的元素的值
}

在这个例子中,指针 ptr 从数组的开始地址开始,每次循环递增 ptr 以移动到下一个元素,直到它指向数组的末尾。

5. 使用标准库函数

如果你使用的是C99或更新的标准,你可以使用 sizeof 关键字来获取数组的大小,这使得代码更加简洁。

for (int *ptr = array; ptr < array + sizeof(array) / sizeof(array[0]); ptr++) {printf("%d ", *ptr);
}

注意事项

  • 确保不要越界访问数组,这意味着指针不应该超过数组的末尾。
  • 使用指针遍历数组时,要小心不要解引用未初始化或非法的指针。
  • 在多维数组的情况下,你需要使用多个指针或指针的指针来遍历数组。

使用指针遍历数组是一种高效的方法,它允许你直接操作内存中的数据,但也需要你注意指针的使用和内存安全。
(二)如何避免内存泄漏?
在C语言中避免内存泄漏,可以遵循以下几个原则和实践:

  1. 及时释放内存:在使用完动态分配的内存后,一定要记得调用free()函数来释放内存。这是避免内存泄漏的基本做法。

  2. 避免重复释放内存:一旦内存被释放,应避免再次释放同一块内存。这可以通过在释放后将指针设置为NULL来实现,从而防止悬垂指针问题。

  3. 检查内存分配的返回值:在使用malloc()calloc()realloc()分配内存时,必须检查返回值是否为NULL,以确保内存分配成功。如果分配失败,应避免使用该内存块。

  4. 使用内存泄漏检测工具:使用如Valgrind、AddressSanitizer等工具来检测程序中的内存泄漏。这些工具可以分析程序的内存使用情况,发现潜在的内存泄漏问题。

  5. 编写测试代码:针对可能出现内存泄漏的代码段,编写专门的测试代码来验证其正确性。通过模拟各种场景和边界条件,确保内存分配和释放的正确性。

  6. 日志记录和监控:在关键位置添加日志记录,以便跟踪内存分配和释放的过程。同时,可以使用监控工具来实时观察程序的内存使用情况,及时发现异常。

  7. 避免野指针和悬垂指针:确保指针在使用前已经被正确初始化,避免指向随机或无效的内存地址。

  8. 团队合作和代码审查:通过团队成员之间的相互检查和交流,可以及时发现并纠正潜在的内存泄漏问题。定期的代码审查和测试也是确保程序质量的关键环节。

  9. 使用智能指针:虽然C语言没有内置的智能指针,但可以通过封装内存分配和释放逻辑来模拟智能指针的行为,自动管理内存。

  10. 优化内存使用:通过减少不必要的内存分配和重用已分配的内存,可以降低内存泄漏的风险。

遵循这些原则和实践,可以有效地减少C语言中内存泄漏的风险,提高程序的稳定性和性能。

(三)基于AI的学习




本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/840518.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

项目代码性能优化

性能优化之: 1. //减少了服务器请求次数 防抖: 防止用户在短时间内操作多次(发送多次无意义请求) 验证码 - 通过使用input验证码/滑动验证/选图片等, 验证插件, 实现先验证, 再发送请求! 节流 - 让某个函数在指定时间内, 只调用一次( 肯定会和定时器搭配使用 ) …

高级语言程序设计作业

班级:https://edu.cnblogs.com/campus/fzu/2024C 作业要求: https://edu.cnblogs.com/campus/fzu/2024C/homework/13307 姓名:鲁申如 学号:102300123

HCIA-02 OSI和TCP参考模型

简单介绍OSI和TCP模型网络基础知识复习 1.交换机用于连接多台主机形成广播域,组成局域网。 2.主机间通信使用MAC地址进行,限制广播域大小需使用路由器。 3.跨广播域通信应使用IP地址 网络参考模型与标准 1.网络参考模型定义了网络设备间通信的标准,确保不同厂商设备兼容。 2…

非机动车占道AI识别算法

非机动车占道AI识别算法通过安装在交通道口的摄像头,非机动车占道AI识别算法运行AI识别算法对摄像头捕获的图像或视频流进行实时分析,识别非机动车占道行为。一旦检测到占道行为,系统会自动触发告警,并将信息发送至后台。接收告警信息,通知管理人员及时处理,并保存相关证…

车间工人SOP流程检测系统

车间工人SOP流程检测系统通过安装在车间现场的监控摄像头, 车间工人SOP流程检测系统自动检测工人在生产过程中的行为。这包括任务执行的顺序、使用的工具是否正确,以及是否遵守了安全规定,确保每一步操作都符合预设的标准作业流程。系统利用深度学习模型检测人体关键部位的骨…

泥石流滑坡灾害检测系统

泥石流滑坡灾害检测系统通过部署在关键路段的高清摄像头,泥石流滑坡灾害检测系统能够捕捉到山体的微小变化。利用YOLOv5+CNN算法,系统能够分析这些图像数据,识别出潜在的滑坡迹象。一旦检测到山体滑坡泥石流异常情况,系统会立即发出预警,为相关部门提供宝贵的反应时间。通…

去控制流平坦化混淆

特征 有大量的switch跳转视图使用ctrl shift D打开d810选择ollvm变干净了许多

newstar2024 reverse

Newstar 2024 --Reverse base64 无壳shift f12查找字符串 换表的base64加密Simple_encryption打开主函数 直接查看buffer,逆向破解 enc = [0x47, 0x95, 0x34, 0x48, 0xA4, 0x1C, 0x35, 0x88, 0x64, 0x16,0x88, 0x07, 0x14, 0x6A, 0x39, 0x12, 0xA2, 0x0A, 0x37, 0x5C,0x07, 0x…

华为技术岗位笔试面试题汇总-第二篇

本篇文章是华为技术岗位笔试&面试题,第二篇。 后续将持续推出互联网大厂,如阿里,腾讯,百度,美团,头条等技术面试题目,以及答案,专家出题人分析汇总。 欢迎大家点赞关注转发。说在前面 本篇文章是华为技术岗位笔试&面试题,第二篇。 后续将持续推出互联网大厂,…

第八次高级程序语言设计课

班级:https://edu.cnblogs.com/campus/fzu/2024C 作业要求: https://edu.cnblogs.com/campus/fzu/2024C/homework/13307 学号:102400115 姓名:洪育豪 11.13.111.13.211.13.311.13.611.13.712.9.112.9.212.9.312.9.812.9.9

Maui Blazor 设置全屏以及去掉标题栏 (Windows 平台)

编辑 MauiProgram.cs 文件隐藏标题栏,隐藏边框已知问题, 可调整大小窗体, 标题栏会残留一点像素作为调整句柄using Microsoft.Extensions.Logging; using Microsoft.Maui.LifecycleEvents; #if WINDOWS using Microsoft.UI; using Microsoft.UI.Windowing; using Microsoft.UI.…

360评估参评人拉帮结派搞小圈子给别人恶意评低分怎么办?

离了大谱,苦心准备的评估活动,有参评人拉帮结派搞小圈子给别人恶意评低分,导致最终结果不能体现被评价人的实际工作表现。以上情况在我们客户的实际360度评估过程中还挺常见,不过放在简简人事系统中可以很轻松的应对这种情况,简简人事360度评估系统有一个得分分布控制功能…