学期2024-2025-1 学号20241317 《计算机基础与程序设计》第十一周学习总结
学期2024-2025-1 学号20241317 《计算机基础与程序设计》第十一周学习总结
作业信息
这个作业属于哪个课程 | <班级的链接>(如2024-2025-1-计算机基础与程序设计) |
---|---|
这个作业要求在哪里 | <作业要求的链接>(如2024-2025-1计算机基础与程序设计第一周作业) |
这个作业的目标 | <写上具体方面> |
作业正文 | https://www.cnblogs.com/manurios/p/18593468 |
教材学习内容总结
C语言程序设计第十章通常涉及的是C语言中的高级主题。不过,由于不同的教材和课程可能会有不同的章节安排,以下是一个较为通用的第十章知识点总结,可能包括但不限于以下内容:
-
预处理器指令:
#include
:用于包含标准库或用户自定义的头文件。#define
:用于定义宏。#ifdef
、#ifndef
、#endif
:用于条件编译。
-
位运算:
- 位与(&)、位或(|)、位非(~)、位异或(^)。
- 位左移(<<)和位右移(>>)。
-
文件操作:
fopen
、fclose
、fread
、fwrite
、fprintf
、fscanf
、fgets
、fputc
、fgetc
等函数的使用。- 文件指针和文件缓冲区的概念。
-
结构体:
- 结构体的定义和使用。
- 结构体数组。
- 结构体与函数。
-
联合(Union):
- 联合的定义和使用。
- 联合与结构体的区别。
-
枚举(Enum):
- 枚举类型的定义和使用。
-
动态内存分配:
malloc
、calloc
、realloc
、free
函数的使用。
-
指针的高级应用:
- 指针和数组的关系。
- 指针和函数的关系。
- 指针的指针。
-
递归:
- 递归函数的定义和使用。
- 递归的注意事项和常见问题。
-
信号处理:
signal
函数的使用。- 信号集和信号掩码。
-
多线程编程(如果教材包含):
pthread
库的使用。- 线程的创建、同步和销毁。
-
网络编程(如果教材包含):
- 套接字(Socket)的概念。
- 网络通信的基本流程。
请注意,具体内容可能会根据你所使用的教材或课程有所不同。如果你有具体的教材或课程大纲,可以提供更详细的信息,以便给出更准确的知识点总结。
通过 AI 工具总结一下内容,自己再补充
通过思维导图形成知识体系
看懂就过,看不懂,学习有心得的记一下
教材学习中的问题和解决过程(先问 AI)
(一个模板:我看了这一段文字 (引用文字),有这个问题 (提出问题)。 我查了资料,有这些说法(引用说法),根据我的实践,我得到这些经验(描述自己的经验)。 但是我还是不太懂,我的困惑是(说明困惑)。【或者】我反对作者的观点(提出作者的观点,自己的观点,以及理由)。 )
- 问题1:联合与结构体的区别是什么?
- 问题1解决方案:在C语言中,联合(Union)和结构体(Structure)都是用户定义的复合数据类型,但它们之间存在一些关键的区别:
-
存储方式:
- 结构体:结构体中的所有成员都占用自己的内存空间,它们是同时存储的。这意味着结构体的大小是其所有成员大小的总和(考虑到内存对齐)。
- 联合:联合中的所有成员共享同一块内存空间。在任意时刻,联合只能存储其中一个成员的值。联合的大小等于其最大成员的大小(也要考虑内存对齐)。
-
内存占用:
- 结构体:由于所有成员都同时存储,结构体通常占用更多的内存。
- 联合:由于成员共享内存,联合通常占用较少的内存。
-
使用目的:
- 结构体:用于存储不同的、相关的数据项,这些数据项不一定在所有时间都同时使用。
- 联合:用于存储多个数据项,但这些数据项在同一时间只能使用其中一个。联合常用于需要节省空间或处理多种数据类型的场景。
-
访问成员:
- 结构体:可以通过点操作符(
.
)或箭头操作符(->
)安全地访问所有成员,不会覆盖其他成员。 - 联合:虽然也可以通过点操作符(
.
)或箭头操作符(->
)访问成员,但访问一个成员可能会覆盖另一个成员的值,因此需要小心使用。
- 结构体:可以通过点操作符(
-
初始化:
- 结构体:可以初始化所有成员,也可以只初始化部分成员(使用指定初始化器)。
- 联合:只能初始化一个成员,因为所有成员共享内存。
-
清零:
- 结构体:使用
memset
清零结构体会清零所有成员。 - 联合:使用
memset
清零联合只会清零共享的内存区域。
- 结构体:使用
-
赋值:
- 结构体:不能直接将一个结构体赋值给另一个结构体,除非使用
memcpy
或结构体赋值运算符(C11标准引入)。 - 联合:可以直接将一个联合赋值给另一个联合,因为它们共享内存。
- 结构体:不能直接将一个结构体赋值给另一个结构体,除非使用
-
传递和返回:
- 结构体:作为函数参数时,通常是通过值传递或引用传递。
- 联合:作为函数参数时,也可以通过值传递或引用传递,但由于共享内存的特性,有时可以直接传递联合的地址。
根据具体的应用场景和需求,开发者可以选择使用结构体或联合来存储和管理数据。
- 问题2:为什么将一个联合赋值给另一个联合,它们共享内存
- 问题2解决方案:在C语言中,将一个联合赋值给另一个联合,它们共享内存的原因是因为联合(union)是一种特殊的数据结构,其内部的所有成员都共享同一块内存空间。这意味着无论联合中定义了多少个成员,它们实际上都是同一个存储位置的别名。
以下是几个关键点来解释为什么联合赋值会导致它们共享内存:
-
内存共享机制:
- 联合的定义使得它的所有成员都从同一块内存地址开始存储。因此,当一个联合被赋值给另一个联合时,它们实际上都指向了同一块内存区域。
-
地址相同:
- 当你将一个联合变量赋值给另一个时,你只是复制了这块内存的地址,而不是内存中的内容。这意味着两个联合变量现在指向了同一块内存,任何对这块内存的修改都会反映在两个联合变量上。
-
节省空间:
- 联合的设计初衷之一是为了节省空间。通过共享内存,联合可以只占用最大成员所需的空间,而不是所有成员大小的总和。
-
数据覆盖:
- 由于联合的成员共享内存,对一个成员的赋值会覆盖其他成员的值。因此,当你将一个联合赋值给另一个联合时,你实际上是在复制了这块内存的当前状态,而不是它们的独立副本。
-
不可预测的行为:
- 如果同时通过两个联合变量访问和修改内存,可能会导致不可预测的行为,因为它们实际上访问的是同一块内存区域。
-
赋值语义:
- 在C语言中,当一个联合被赋值给另一个联合时,这种赋值操作是通过内存拷贝实现的,而不是值拷贝。这意味着两个联合变量将共享同一块内存空间。
因此,当你将一个联合赋值给另一个联合时,它们共享内存是因为联合的数据结构定义了这样的内存共享机制,这也是联合与结构体的一个主要区别。结构体的成员各自拥有独立的内存空间,而联合的成员则共享相同的内存空间。
- ...
基于AI的学习
问题1:细讲指针
回答:指针是C语言中一个非常核心和强大的概念,它提供了对内存的直接访问和操作能力。以下是指针的一些基础知识和详细解释:
1. 指针的定义
指针是一个变量,其存储的是另一个变量的内存地址。指针变量的声明通常包括指针类型和指针名,例如:
int *ptr; // ptr是一个指向整型变量的指针
2. 指针的类型
指针的类型决定了它可以指向的数据类型。例如:
int *ptr
指向一个整型变量。float *ptr
指向一个浮点型变量。char *ptr
指向一个字符型变量。
3. 指针的初始化
指针变量在使用前应该被初始化,以避免指向随机的内存地址。可以初始化为NULL或者具体的地址:
int a = 10;
int *ptr = &a; // ptr指向变量a的地址
int *ptr = NULL; // ptr初始化为NULL
4. 指针的解引用
通过指针访问其指向的变量的值称为解引用。使用*
操作符来解引用指针:
int a = 10;
int *ptr = &a;
int value = *ptr; // value现在等于10
5. 指针的算术
指针可以进行加法和减法运算,但只能对同类型的指针进行。指针的加法实际上是按照指针指向的数据类型的大小进行跳转:
char str[] = "Hello";
char *ptr = str;
ptr++; // ptr现在指向'e'
6. 指针和数组
指针和数组紧密相关。数组名本身可以作为指向数组第一个元素的指针:
int arr[5] = {1, 2, 3, 4, 5};
int *ptr = arr; // ptr指向数组的第一个元素
7. 指针和函数
指针可以作为函数参数传递,这允许函数直接修改传入的变量:
void increment(int *num) {
(*num)++; // 增加指针指向的值
}
8. 指针的指针
指针的指针是指指向另一个指针的指针。这在处理多级指针和动态内存分配时非常有用:
int a = 10;
int *ptr1 = &a;
int **ptr2 = &ptr1;
9. 动态内存分配
使用malloc
、calloc
、realloc
和free
等函数可以在堆上动态分配和释放内存。这些函数返回指向分配内存的指针:
int *ptr = (int *)malloc(sizeof(int)); // 分配一个整型大小的内存
if (ptr != NULL) {
*ptr = 20; // 使用分配的内存
free(ptr); // 释放内存
}
10. 指针和字符串
在C语言中,字符串通常以字符数组的形式存储,而字符数组的地址可以作为指向字符串的指针:
char str[] = "Hello";
char *ptr = str; // ptr指向字符串的首地址
11. 指针的比较
可以比较两个指针是否相等,或者它们是否指向同一块内存区域。也可以比较指针的值(即它们存储的地址)。
12. 指针的注意事项
- 避免野指针(未初始化的指针)。
- 避免内存泄漏(分配了内存但没有释放)。
- 注意指针的生命周期,确保在指针使用完毕后释放内存。
- 避免越界访问,这可能导致程序崩溃或数据损坏。
指针是C语言中非常强大的工具,但也需要谨慎使用,以避免常见的错误和安全问题。
问题2:#ifdef、#ifndef、#endif:用于条件编译。如何使用
回答:#ifdef
、#ifndef
和 #endif
是 C 语言预处理器指令,用于条件编译,即根据特定的条件决定是否编译代码的某个部分。这些指令通常用于根据不同的平台、操作系统或编译器选项来包含或排除代码段。
以下是如何使用这些指令的详细说明:
1. #ifdef
(If defined)
#ifdef
指令用于检查一个宏是否已经定义。如果宏已经定义,则编译下面的代码块;如果没有定义,则跳过该代码块。
#ifdef MACRO
// 如果宏MACRO已经定义,则编译这段代码
#endif // MACRO
2. #ifndef
(If not defined)
#ifndef
指令用于检查一个宏是否没有定义。如果宏没有定义,则编译下面的代码块;如果已经定义,则跳过该代码块。
#ifndef MACRO
// 如果宏MACRO没有定义,则编译这段代码
#endif // MACRO
3. #endif
(End if)
#endif
指令用于结束由 #ifdef
或 #ifndef
开始的条件编译块。
使用示例
假设我们有一个宏 DEBUG
,我们想要在调试模式下编译某些代码,而在发布模式下不编译这些代码:
#ifdef DEBUG
#include <stdio.h>
printf("Debug information: Variable x = %d\n", x);
#endif // DEBUG
在上面的代码中,如果 DEBUG
宏被定义了,那么包含 printf
的代码块将被编译;否则,这段代码将被编译器忽略。
同样地,使用 #ifndef
:
#ifndef DEBUG
// 这段代码只有在DEBUG宏未定义时才会被编译
#endif // DEBUG
组合使用
#ifdef
和 #ifndef
可以与 #else
结合使用,以提供两种互斥的编译选项:
#ifdef MACRO
// 如果MACRO定义了,编译这段代码
#else
// 如果MACRO没有定义,编译这段代码
#endif
这种结构允许你根据宏是否存在来选择两个代码块中的一个进行编译。
宏定义
宏通常在编译前通过编译器命令行选项定义,或者在代码中使用 #define
指令定义:
#define MACRO
或者在编译时通过命令行定义(以 GCC 为例):
gcc -DMACRO source.c
使用条件编译可以使得代码更加灵活,能够适应不同的编译环境和配置需求。
三个原则:
- 切勿原封不动地接受生成式人工智能工具的输出;确保对其进行评估、完善和修改(或提示),以适应您的目标。
- 切勿将任何个人数据(自己、同学、老师等)或版权材料纳入到你的提示词中。这个可以说是保护个人隐私的最起码的举措。
- 所有人工智能生成工具都容易产生幻觉,因此会生成不准确或误导性的信息,要学会甄别信息真假
选择至少2个知识点利用chatgpt等工具进行苏格拉底挑战,并提交过程截图,提示过程参考下面内容
“我在学***X知识点,请你以苏格拉底的方式对我进行提问,一次一个问题”
核心是要求GPT:“请你以苏格拉底的方式对我进行提问”
然后GPT就会给你提问,如果不知道问题的答案,可以反问AI:“你的理解(回答)是什么?”
如果你觉得差不多了,可以先问问GPT:“针对我XXX知识点,我理解了吗?”
GPT会给出它的判断,如果你也觉得自己想清楚了,可以最后问GPT:“我的回答结束了,请对我的回答进行评价总结”,让它帮你总结一下。
代码调试中的问题和解决过程
- 问题1:XXXXXX
- 问题1解决方案:XXXXXX
- 问题2:XXXXXX
- 问题2解决方案:XXXXXX
- ...
代码托管
(statistics.sh脚本的运行结果截图)
上周考试错题总结
- 错题1及原因,理解情况
- 错题2及原因,理解情况
- ...
其他(感悟、思考等,可选)
xxx
xxx
学习进度条
代码行数(新增/累积) | 博客量(新增/累积) | 学习时间(新增/累积) | 重要成长 | |
---|---|---|---|---|
目标 | 5000行 | 30篇 | 400小时 | |
第一周 | 200/200 | 2/2 | 20/20 | |
第二周 | 300/500 | 2/4 | 18/38 | |
第三周 | 500/1000 | 3/7 | 22/60 | |
第四周 | 300/1300 | 2/9 | 30/90 |
尝试一下记录「计划学习时间」和「实际学习时间」,到期末看看能不能改进自己的计划能力。这个工作学习中很重要,也很有用。
耗时估计的公式
:Y=X+X/N ,Y=X-X/N,训练次数多了,X、Y就接近了。
-
计划学习时间:XX小时
-
实际学习时间:XX小时
-
改进情况:
(有空多看看现代软件工程 课件
软件工程师能力自我评价表)
参考资料
- 《计算机科学概论(第七版)》
- ...