- 博客(39)
- 收藏
- 关注
原创 C语言知识扩展:函数栈帧的创建和销毁
栈帧是函数调用时在程序栈上分配的一块内存区域,用于存储函数的执行上下文。每个函数调用都会创建自己的栈帧,当函数返回时,对应的栈帧会被销毁。可以把栈帧想象成一个临时的"工作台",函数在这个工作台上完成自己的工作,工作完成后就把工作台清空,让下一个函数使用。函数栈帧的创建和销毁是程序执行的基础机制。栈帧的结构:包含参数、返回地址、旧EBP、局部变量等部分创建过程:参数压栈、返回地址压栈、设置新栈帧等步骤销毁过程:恢复寄存器、释放空间、恢复旧EBP、返回等步骤调试技巧:使用VS2022的调试工具观察栈帧。
2025-12-25 17:07:31
993
原创 C语言入门(三十二):预处理详解(2)
许多C的编译器提供了⼀种能⼒,允许在命令⾏中定义符号。⽤于启动编译过程。例如:当我们根据同⼀个源⽂件要编译出⼀个程序的不同版本的时候,这个特性有点⽤处。(假定某个程序中声明了⼀个某个⻓度的数组,如果机器内存有限,我们需要⼀个很⼩的数组,但是另外⼀个机器内存⼤些,我们需要⼀个数组能够⼤些。这个只能在gcc环境的情况才能看到,这里我们就不演示了int main()int i = 0;for(i = 0;//linux 环境演⽰。
2025-12-20 19:55:48
870
原创 C语言入门(三十一):预处理详解(1)
C语⾔设置了⼀些预定义符号,可以直接使⽤,预定义符号也是在预处理期间处理的。__FILE__ 进⾏编译的源⽂件__LINE__ ⽂件当前的⾏号__DATE__ ⽂件被编译的⽇期__TIME__ ⽂件被编译的时间__STDC__ 如果编译器遵循ANSI C,其值为1否则未定义int main()//如果编译器支持则返回值是1,否则会报错误,在VS2022是不支持的return 0;输出结果:int main()return 0;
2025-12-20 19:01:01
607
原创 C语言入门(三十):编译和链接
我们在 test.c ⽂件中每⼀次使⽤Add 函数和 g_val 的时候必须确切的知道Add 和g_val 的地址,但是由于每个⽂件是单独编译的,在编译器编译test.c 的时候并不知道Add 函数和 g_val变量的地址,所以暂时把调⽤ Add 的指令的⽬标地址和g_val 的地址搁置。前⾯我们⾮常简洁的讲解了⼀个C的程序是如何编译和链接,到最终⽣成可执⾏程序的过程,其实很多 内部的细节⽆法展开讲解。将源代码程序被输⼊扫描器,扫描器的任务就是简单的进⾏词法分析,把代码中的字符分割成⼀系列 的记号(
2025-12-18 14:29:26
817
原创 C语言入门(二十九):文件操作
磁盘(硬盘)上的⽂件是⽂件。程序⽂件、数据⽂件(从⽂件功能的⻆度来分类 的)上⾯说的适⽤于所有输⼊流⼀般指适⽤于标准输⼊流和其他输⼊流(如⽂件输⼊流);所有输出流⼀般指适⽤于标准输出流和其他输出流(如⽂件输出流)这里我们就先介绍几个fputc的使用int main()//打开文件return 1;//写文件//关闭文件fclose(pf);pf == NULL;return 0;fgetc的使用fgetc的使用int main()//打开文件return 1;
2025-12-17 15:22:53
732
原创 C语言入门(二十八):动态内存管理(2)
C/C++程序内存分配的⼏个区域:1. 栈区(stack):在执⾏函数时,函数内局部变量的存储单元都可以在栈上创建,函数执⾏结束时 这些存储单元⾃动被释放。栈内存分配运算内置于处理器的指令集中,效率很⾼,但是分配的内 存容量有限。栈区主要存放运⾏函数⽽分配的局部变量、函数参数、返回数据、返回地址等。《函数栈帧的创建和销毁》2. 堆区(heap):⼀般由程序员分配释放,若程序员不释放,程序结束时可能由OS(操作系统) 回收。分配⽅式类似于链表。
2025-12-16 22:00:00
902
原创 C语言入门(二十七):动态内存管理(1)
当是情况2的时候,原有空间之后没有⾜够多的空间时,扩展的⽅法是:在堆空间上另找⼀个合适⼤⼩ 的连续空间来使⽤。有时候我们需要的空间⼤⼩在程序运⾏的时候才能知 道,那数组的编译时开辟空间的⽅式就不能满⾜了。所以如果我们对申请的内存空间的内容要求初始化,那么可以很⽅便的使⽤calloc函数来完成任务。当是情况1的时候,要扩展内存就直接原有内存之后直接追加空间,原来空间的数据不发⽣变化。:赋值的内容,第一次循环是 1,第二次是 2,……以上是部分的讲解内容,剩下的就放在下一章里面去!
2025-12-15 21:26:32
1000
原创 知识扩展:进制的详细介绍
简单理解:进制就是“逢几进一”的计数方式。就像平时我们数数:数到9,下一个就是10(这是十进制,逢10进1)二进制只有0和1,数到1,下一个就是10(逢2进1)时钟是60进制(60秒=1分钟,60分钟=1小时)常见进制十进制二进制八进制十六进制十转其他:除基数,取余数,倒着读其他转十:每位乘(基数^位置),然后加起来二/八/十六互转:利用“3位二进制=1位八进制”,“4位二进制=1位十六进制”
2025-12-05 12:00:00
1442
11
原创 C语言入门(二十五):自定义类型:结构体
这里的位是指二进制位位段的成员必须是int 、 unsigned int 或 signed int,在C99中位段成员的类型也可以 选择其他类型。位段的成员名后边有⼀个冒号和⼀个数字。像这种'' : 数字 ''这种结果的表达式,称之为 位段式结构int a : 2;表示成员a只占用 2 个比特位。//前面加 _ 是为了好区分,这里可加可不加int _b : 5;int main()//输出8return 0;
2025-12-03 23:11:07
1419
32
原创 C语言入门(二十四):数据在内存中的存储
其实超过⼀个字节的数据在内存中存储的时候,就有存储顺序的问题,按照不同的存储顺序,我们分 为⼤端字节序存储和⼩端字节序存储,下⾯是具体的概念:⼤端(存储)模式:(反着来)是 指数据的低位字节内容保存在内存的⾼地址处,⽽数据的⾼位字节内容,保存在内存的低地址处⼩端(存储)模式:(正着来)是 指数据的低位字节内容保存在内存的低地址处,⽽数据的⾼位字节内容,保存在内存的⾼地址处。上述概念需要记住,⽅便分辨⼤⼩端。
2025-12-01 00:29:02
1589
22
原创 C语言入门(二十二):字符函数和字符串函数(2)
这个头⽂件中说明 的,C语⾔程序启动的时候就会使⽤⼀个全局的变量errno来记录程序的当前错误码,只不过程序启动 的时候errno是0,表⽰没有错误,当我们在使⽤标准库中的函数的时候发⽣了某种错误,就会将对应 的错误码,存放在errno中,⽽⼀个错误码的数字是整数很难理解是什么意思,所以每⼀个错误码都 是有对应的错误信息的。⽐较str1和str2的前num个字符,如果相等就继续往后⽐较,最多⽐较num个字⺟,如果提前发现不⼀ 样,就提前结束,⼤的字符所在的字符串⼤于另外⼀个。(地址 &arr1[0])
2025-11-28 00:00:00
1277
16
原创 C语言入门(二十一):字符函数和字符串函数(1)
将src指向的字符赋值给dest指向的位置,然后检查赋值结果是否为0(即是否拷贝了'\0')C语⾔中有⼀系列的函数是专⻔做字符分类的,也就是⼀个字符是属于什么类型的字符的。作为结束标志,strlen函数返回的是在字符串中 '\0' 前⾯出现的字符个数。,是-32完成的效果,有了转换函数,就可以直接使⽤ 数。• ⽬标空间必须有⾜够的⼤,能容纳下源字符串的内容。,原因就在于它们计算的最后的结果是无符号的,所以是。• 注意函数的返回值为size_t,是⽆符号的。第二个strlen里面的值,输出的结果应该是。
2025-11-26 14:20:24
1270
21
原创 C语言入门 (二十):指针(6)
x64坏境是8,x86的坏境是4 ---a是首元素的地址,它的类型是int* ,所以a+0还是首元素的地址,是地址的话,它的大小就是4或者8,根据x64和x86坏境决定的。输出4 ---a是首元素的地址,*a就是首元素,首元素是int,所以是4个字节,这里的 *a == a[0]4或者8 ---arr是数组名,表示的是首元素的地址,arr+0还是首元素的地址,地址的大小就是4或者8。4或者8 ---arr表示的是首元素的地址,arr+0还是首元素的地址,地址的大小就是4或者8。
2025-11-23 16:41:49
1704
18
原创 C语言入门(十九):指针(5)
如果你把函数的指针(地址)作为参数传递给另⼀个函数,当这个指针被⽤来调⽤其所指向的函数 时,被调⽤的函数就是回调函数。这个代码是利用switch语句来把我们的按键归为一个情况,1就是加入加号的代码里面去,后面的是一个意思,这里的default是输入了不是case里面的数字,而是输入了其他的,那么就会执行整个代码,即打印出‘’选择错误‘’这四个字。我们可以把调⽤的函数的地址以参数的形式 传递过去,使⽤函数指针接收,函数指针指向什么函数就调⽤什么函数,这⾥其实使⽤的就是回调函 数的功能。
2025-11-20 23:02:54
1697
17
原创 C语言入门(十八):指针(4)
所以,根据数组名是数组⾸元素的地址这个规则,⼆维数组的数组名表⽰的就是第⼀⾏的地址,是⼀ 维数组的地址。根据上⾯的例⼦,第⼀⾏的⼀维数组的类型就是 型就是数组指针类型 int [5] ,所以第⼀⾏的地址的类型。⾸先我们再次理解⼀下⼆维数组,⼆维数组其实可以看做是每个元素是⼀维数组的数组,也就是⼆维 数组的每个元素是⼀个⼀维数组。那就意味着⼆维数组传参本质上也是传递了地址,传递的是第⼀ ⾏这个⼀维数组的地址,那么形参也是可以写成指针形式的。数组指针变量是⽤来存放数组地址的,那怎么获得数组的地址呢?
2025-11-17 21:39:25
1359
17
原创 C语言入门(十七):指针(3)
同理arr[i] 应该等价于*(arr+i),数组元素的访问在编译器处理的时候,也是转换成⾸元素的地址+偏移 量求出元素的地址,然后解引⽤来访问的。这⾥我们使⽤ &arr[0] 的⽅式拿到了数组第⼀个元素的地址,但是其实数组名本来就是地址,⽽且 是数组⾸元素的地址,我们来做个测试。arr[i]是访问arr数组的元素,arr[i]找到的数组元素指向了整型⼀维数组,parr[i][j]就是整型⼀维数 组中的元素。这⾥的数组名表⽰整个数组,取出的是整个数组的地址(整个数组的地址和数组⾸元素 的地址是有区别的)
2025-11-15 23:35:20
1136
15
原创 C语言入门(十六):指针(2)
就是为了 不能被修改,如果p拿到a的地址就能修改a,这样就打破了const的限制,这是不合理的,所以应该让 p拿到a的地址也不能修改a,那接下来怎么做呢?如果明确知道指针指向哪⾥就直接赋值地址,如果不知道指针应该指向哪⾥,可以给指针赋值NULL. NULL 是C语⾔中定义的⼀个标识符常量,值是0,0也是地址,这个地址是⽆法使⽤的,读写该地址 会报错。这就是const的作⽤。const如果放在*的右边,修饰的是指针变量本⾝,保证了指针变量的内容不能修改,但是指针指 向的内容,可以通过指针改变。
2025-11-12 00:24:39
1126
18
原创 C语言入门(十五):指针(1)
前⾯的内容我们了解到,32位机器假设有32根地址总线,每根地址线出来的电信号转换成数字信号后 是1或者0,那我们把32根地址线产⽣的2进制序列当做⼀个地址,那么⼀个地址就是32个bit位,需要4 个字节才能存储。我们知道计算机上CPU(中央处理器)在处理数据的时候,需要的数据是在内存中读取的,处理后的 数据也会放回内存中,那我们买电脑的时候,电脑上内存是8GB/16GB/32GB等,那这些内存空间如 何⾼效的管理呢。在上⾯的代码中,将⼀个int类型的变量的地址赋值给⼀个char*类型的指针变量。
2025-11-08 18:54:17
1277
18
原创 C语言入门(十四): 操作符详解(2)
即使有了操作符的优先级和结合性,我们写出的表达式依然有可能不能通过操作符的属性确定唯⼀的 计算路径,那这个表达式就是存在潜在⻛险的,建议不要写出特别复杂的表达式。
2025-11-04 17:12:59
1653
16
原创 C语言入门(十三):操作符详解(1)
16进制的数字每⼀位是0~9,a~f的,0~9,a~f的数字,各⾃写成2进制,最多有4个2进制位就⾜够了, ⽐如f的⼆进制是1111,所以在2进制转16进制数的时候,从2进制序列中右边低位开始向左每4个2进 制位会换算⼀个16进制位,剩余不够4个⼆进制位的直接换算。8进制的数字每⼀位是0~7的,0~7的数字,各⾃写成2进制,最多有3个2进制位就⾜够了,⽐如7的⼆ 进制是111,所以在2进制转8进制数的时候,从2进制序列中右边低位开始向左每3个2进制位会换算⼀ 个8进制位,剩余不够3个2进制位的直接换算。
2025-11-01 23:06:20
1165
17
原创 C语言入门(十二):函数的递归
在这个解题的过程中,我们就是使⽤了⼤事化⼩的思路 把Print(1234) 打印1234每⼀位,拆解为⾸先Print(123)打印123的每⼀位,再打印得到的4 把Print(123) 打印123每⼀位,拆解为⾸先Print(12)打印12的每⼀位,再打印得到的3 直到Print打印的是⼀位数,直接打印就⾏。函数不返回,函数对应的栈帧空间就⼀直占⽤,所以如果函数调⽤中存在递归调⽤的话,每⼀次递归 函数调⽤都会开辟属于⾃⼰的栈帧空间,直到函数递归不再继续,开始回归,才逐层释放栈帧空间。
2025-10-28 12:39:41
1625
16
原创 VS2022的使用小技巧
当程序员写完代码,测试再对程序进⾏测试,直到程序的质量符合交付给⽤⼾ 使⽤的标准,这个时候就会设置为 release ,编译产⽣的就是 release 版本的可执⾏程序,这个 版本是⽤⼾使⽤的,⽆需包含调试信息等。调试⼀个程序,⾸先是承认出现了问题,然后通过各种⼿段去定位问题的位置,可能是逐过程的调 试,也可能是隔离和屏蔽代码的⽅式,找到问题所的位置,然后确定错误产⽣的原因,再修复代码, 重新测试。在VS上切换到X64,这个使⽤的顺序就是相反的,在Release版本的程序中,这个使⽤的顺序也是相反 的。
2025-10-24 12:41:06
1200
11
原创 C语言趣味小游戏----扫雷游戏
当然上面的数组还可以优化一下,上面是只能存放11个字符,这样的棋盘大小就是11*11的规模,但是当我们需要更大的棋盘的时候,我们只能将11更改,然后才能实现更大的棋盘规模,这样显的非常麻烦,每换一次模式,我们就要改这个数组,于是我们有一个方法可以避免这样麻烦,就是设置参数,将棋盘的行与列分别用row 与 col 来进行传参设置,这样需要什么就要什么,非常的方便。将9*9棋盘的雷信息放到11*11棋盘里面去,加'0'是转换为雷的个数,1 2 3 4这样的,之前那是ASCOLL值的数字。
2025-10-20 23:11:12
3069
18
原创 C语言入门(十一)续:函数的深入认识
1.单个⽂件函数的定义问题:判断一年是否是闰年函数定义(main函数以上的代码)= 0)) || (year % 400 == 0))//计算闰年return 1;//是闰年则返回值为1elsereturn 0;//不是闰年则返回值为0return 0;计算闰年的方法:int main()//输出年份//通过调用函数is_leap_year(year);将返回值穿到int r里面去printf("闰年\n");elseprintf("非闰年\n");return 0;
2025-10-18 11:33:39
843
14
原创 C语言入门(十):函数的深入认识
1.函数的语法形式ret_type 是函数返回类型 , 是⽤来表⽰函数计算结果的类型,有时候返回类型可以是 void ,表⽰什么都不返回fun_name 是函数名, 是为了⽅便使⽤函数;就像⼈的名字⼀样,有了名字⽅便称呼,函数有了名字⽅便调 ⽤,所以函数名尽量要根据函数的功能起的有意义括号中放的是形式参数{}括起来的是函数体ret_type fun_name(形式参数)练习:问题:写一个加法函数,完成2个整型函数的加法操作正常的计算方法正常的计算方法int main()
2025-10-17 21:43:10
1347
8
原创 C语言入门(九):二维数组的介绍
有 ⼀个⽐较迷惑的点,变⻓数组的意思是数组的⼤⼩是可以使⽤变量来指定的,在程序运⾏的时候,根 据变量的⼤⼩来指定数组的元素个数,⽽不是说数组的⼤⼩是可变的。前⾯学习的数组被称为⼀维数组,数组的元素都是内置类型的,如果我们把⼀维数组做为数组的元 素,这时候就是⼆维数组,⼆维数组作为数组元素的数组被称为三维数组,⼆维数组以上的数组统称 为多维数组。像⼀维数组⼀样,也是使⽤⼤括号初始化的。图中最右侧绿⾊的数字表⽰⾏号,第⼀⾏蓝⾊的数字表⽰列号,都是从0开始的,⽐如,我们说:第2 ⾏,第4列,快速就能定位出7。
2025-10-10 23:39:36
1059
12
原创 C语言入门(八):一维数组的深入认识
1.数组的不初始化代码如下它拥有多个函数类型,比如整型,浮点型等等int main()return 0;2.数组的初始化分别有 完全初始化、不完全初始化代码如下数组可以存入字符,数字,小数等等int main()//不完全初始化,后面的数全部会被0填上//完全初始化//不完全初始化//不完全初始化return 0;不完全初始化代码如下。
2025-10-10 22:44:32
1054
2
原创 C语言趣味小游戏----猜数字小游戏
这个代码是我们给游戏设置的规则,如果我们的guess也就是我们输入的数字大于我们的r也就是随机数的话,我们就会给玩家提示你猜大了,同样的,我们猜小,系统就会提示我们猜小了,同样的猜对了也就是下面的那句话,大家可以自己设置的,可以不用和我的一样。1.我们发现了两个函数,一个是menu()一个是game(),其实这个函数名字是可以随便取得,这里我为了好理解,就这样取的变量,menu就是菜单的意思,打开我们的猜数字游戏的界面,game就是游戏嘛,大家应该理解。
2025-09-30 16:15:20
2555
22
原创 C语言入门(七):写一个关机程序、随机函数的基本认识
注意:随机数的整体范围是0-37962,不能超过这数,这个是计算机规定的1.rand函数的基本介绍rand函数的原型作用:可以生成随机数注意:它需要一个头文件,#include<stdlib.h>头文件rand代码的基本代码的使用int main()return 0;输出结果它生成的是一个伪随机数,不是真正的随机数,第一次运行代码的时候,确实是随机出来的,但是你再运行一次代码,我们发现数没有变化。
2025-09-29 23:35:21
1101
14
原创 C语言入门(六):while for do while三大循环的使用,以及goto语句的使用
这里我们将a++改成了+=3,还有a的初始化的值是3,有了这两个条件,我们就可以直接的把if语句判断是否是3的倍数给去掉了,用那个直接代替了,于是我们再一次的优化了代码,占用更少的内存,所以这里我推荐大家使用第二种方法,相当于一步到位。它的作用是用于永久的终止循环,只要break被执行,就会直接跳出循环,继续往后执行,这里当我们n=5的时候,就会执行break程序,然后后面的代码就都不会执行了,于是只有1 2 3 4被打印出来。注意:这里的表达式位置是不能更改的,是固定的,而且它们是用;
2025-09-27 23:31:39
1260
10
原创 C语言入门(五):switch的基本使用
1-5的case情况这里的break可以省略,不用,因为1-5是工作日,是属于一个范围里面的,当这个范围当头的时候,才使用break将它停下来,跳到另一个地方继续计算,即跳到我们的休息日这个范围里面来,break的本质相当于是停止的意思,停止它已经输出正确的值后会继续输出后面的值这种情况。关于上面出现两个情况的原因是:计算机不会因为它的余数是正确的时候停下来,他会继续后面的代码,所以有了2,为了防止这种情况,我们可以加break,终止的意思。这里我们输入1-7的值,都可以有对应的输出值。
2025-09-27 12:36:21
1405
5
原创 C语言入门(四):if语句使用、新的操作符、运算符
原因:这里我们发现,即使我们不是90-100也可以打印出优秀,这也就出错误了,原因是多个关系运算符号不能连用, 这里的计算原理被误解了,当你输入小于90的数的时候,和上面90<=a就会矛盾,值是假的,所以a返回值变成了0,然后0<=100,为优秀,因此会出现这样的情况。加入else if这个代码,我们就可以实现if的嵌套使用,这里的else if相当于还有的时候,给定的另一种会出现的情况,将它也打印出来else后面的if以及下面的代码相当于嵌套在了这一排的else的语句中。来表示相反,反列的意思。
2025-09-25 23:55:54
1405
2
原创 C语言入门(三)续:scanf函数的使用
如果用户输入" abc edf tgh ",在这种有空格的情况下,读取的数有点不一样,这里只会打印出abc,后面的直接没有了,原因:scanf的%s有点不同,它会从当前第一个非空白字符开始读起,直到遇到空白字符(即空格、换行符、制表符等)为止。用户输入一个值,scanf在处理用户输入的值的时候,不会直接读取,会进入一个缓存,只有当用户按enter的时候,才会读取用户输入的值,一直到读完缓存,或则遇到第一个错误,就会停下来。如果非要跳过空白,那你可以这样,就是在%c前面加一个空白字符,
2025-09-22 22:47:08
1994
5
原创 C语言入门(三):计算机的基本计算与操作符以及printf和scanf
放在前面的--或者++则被叫做前置++或者--,放在后面的叫做后置++或者--,两则对于a在数值上来说没有上面变化,但是b却有了不同,这里我们先说前置--,即先-再用,即先a=a-1,然后b=a,所以b=9,a=9,这里后置--则先用再-,即先b=a,a=a-1,所以b=10,a=9,当然++也是一样的原理,也有前置和后置。同理这里也是替换了,这里替换的只能是字符串,此外占位符可以多次使用,注意,printf()有n个占位符的时候,那他的参数应该有n+1个,参数不能小于占位符的数量,否则会出错误。
2025-09-21 22:10:22
1084
5
原创 C语言入门(二):转义字符、函数、sizeof、变量
这个我们也可以将它当中作一个函数,它的作用是用来在键盘上读取一个字符的,有了它我们发现我们的光标处在了xxxxx的最后,而不是...的最后,或者其他不是x后面的位置,移动光标处于x的最后的前提,是有这个函数才行,有了这个函数,我们才能明显的观察到我们的光标向前面移动了一个单位,进一步的解释了 \b 的作用。像这样我们可以看出,通过对比我们可看出 \ 将t进行的转变,将其变成了转义字符 \ t ,\ t 的作用是一个制表符,即光标移到下一个水平制表位,通常是4或者8的倍数,就是将字符的间隔对齐的作用。
2025-09-19 23:40:42
1134
4
原创 如何学习C语言?
打个比方,人类与人类之间可以用许多话语来进行交流,比如中文、英文、日语、法语........等等,像这样人与人之间交流就叫做自然语言,而人类与计算机之间交流却不能用简单的中文,法语来进行交流,我们只能通过程序来进行和计算机交流,而这个交流就要通过C语言来进行,简单来说人与计算机的交流就必须用计算机语言来交流,而计算机语言的C语言就是其中的一种,当然还有其他计算机语言,比如python、java等等都是计算机语言的一种。所以我们应该好好的去学习,慢慢的去学习。五:怎么去维护自己写的代码呢?
2025-09-14 22:30:30
845
5
空空如也
被列入新用户榜上,查看排名访问失败
2025-09-16
TA创建的收藏夹 TA关注的收藏夹
TA关注的人
RSS订阅