C生万物 | 底层之美,莫过于C【下】
接底层之美,莫过于C【上】
十三、常见关键字
1、前言
了解了C语言中的常见运算符,接下来我们来看看C语言中的关键字
- 首先对于关键字,我们要注意的两点是
1、关键字是直接使用的,我们得了解
2、变量名不能是关键字
- 从下面这些可以看出,在C语言中,关键字还是蛮多的,我们尝试着给他们分分类:star2:
- 首先单独说一下【auto】,它比较特殊,因为在编译器中,当你定义一个变量的时候默认就是存在的
- auto,翻译过来就是自动的,在C语言里指得是自动变量,所有你定义的局部变量都是自动创建、自动销毁的,所以局部变量都是auto修饰的
- 就像下面这个整型变量a,你在int的前面加上或是不加auto 都是不会报错的, 原因就是所有局部变量都是auto
//auto int a = 10;
int a = 10; //auto可以省略
2、关键字分类
然后我们再来看一下各种关键字的分类
- 大体地分了几个类,详细的我们到后面【关键字详解】这一章节再细讲
3、有关数据存储的底层原理
- 上面有说到一个寄存器关键字,有关寄存器这个东西,涉及到了数据存储,我们来详细说一下,让大家先了解一下这个底层原理
首先你要知道在计算机中的数据是存放在哪里的
①内存 ②硬盘 ③高速缓存 ④寄存器
然后我们再通过这张图来了解一下
- 对于计算机中的寄存器,其实它所空间是很小的,单位只有字节,但是它的读写速度非常快,可以直接与CPU【中央处理器】进行交互
- 然后越往下这个空间越大,内存的话现在普遍都是8G,16G这样,大一点有32G,不会像很早之前的只有2MB这样;对于硬盘的话,我们去市场上买也是500G,1个T这样的大小
- 继续说回我们的寄存器,因为它的读取速度很快,因此CPU直接到寄存器里面拿数据,但这个时候寄存器内存不够大了怎么办呢?装不过这么多,这个时候我们所知道的高速缓存,也就是Cache,会给寄存器提供内存,那高速缓存里又不够了,这个时候就继续让内存给它提供。这样的话整体地提高了计算机的运行效率
- 好,这里是说到了寄存器相关的底层知识,给大家拓展一下
- 下面就是【register】这个关键字的用法,在定义这个变量b的时候加上了这个关键字,就是【建议】编译器把这个变量放到寄存器中,这里要注意,只是建议,而不是直接放入
- 具体再如何使用大家可以去查阅一些资料,这里不做过多详解
//建议把b放到寄存器中
register int b = 10;
接下去我们单独再来重点讲一下两个关键字📕
4、typedef关键字
首先就是这个【typedef】,这个关键字的话是用来重命名的,用在结构体上会比较多
例如下面这个是【数据结构】中链表的存储结构体,也就是将【struct Linknode】这个结构体名字重命名成LNode,这样之后要定义这个结构体变量的时候就不需要再写【struct Linknode】了,结构体的话我们后面也会详细讲到📚
typedef struct Linknode{
int data[MaxSize];
struct Linknode* next;
}LNode
- 当然它不止应用在结构体上,对于一些数据类型也是可以重命名的,例如下面这个【unsigned int】,后面你在使用【uint】定义变量的时候就和【unsigned int】一样
typedef unsigned int uint;
int main(void)
{
unsigned int num1 = 0;
uint num2 = 0; //与num1一样
return 0;
}
5、static关键字
最后再来说一下这个static关键字,这个关键字的话我在Java专栏中也是有过介绍,感兴趣也可以去看看Java|static关键字
- 这里是来说说C语言中的static关键字,首先你要了解static关键字可以用来修饰什么,它主要是可以用来修饰下面三个
5.1、static关键字修饰局部变量
首先我们来看看static对于局部变量的修饰
void test()
{
int a = 3;
a++;
printf("%d ", a);
}
int main(void)
{
int i = 0;
while (i < 10)
{
test();
i++;
}
return 0;
}
- 你认为上面这段程序会输出什么。看到主程序,使用while循环来控制i变量,当i = 10的时候边不会进入循环,所以是会循环10次,然后看内部的test()函数,每次循环调用这个函数的时候都会定义一个变量a,然后++之后变为4,然后输出
- 所以这段程序的运行结果是会输出10个4
- 然后我们修改一下这个定义的变量a,将其设置为静态变量,也就是在int前面加上一个static修饰
- 那这个时候你认为上面那段程序会打印出什么呢?
static int a = 3;
- 首先你要了解==静态变量的特性==以及其余普通变量之前的区别
①普通的局部变量是放在内存的栈区上的,进入局部范围,变量创建,出了局部范围变量销毁
②当static修饰局部变量时,局部变量是在静态区开辟空间的,这时的局部变量,出了作用域变量不销毁,下次进去作用域,使用的是上一次遗留的数据
(改变了存储位置,由栈区–>静态区,使得变量的生命周期发生了变化)
- 知道了这些,你应该清楚这个打印结果是多少了,没错,就是4~13,每一次进入这个test()函数时,这个变量a将不再被执行,也就是只会在第一次进入这个函数的时候定义,之后就会一直存在,知道这个程序结束时它才会被销毁,所以这个变量a每次保留的便是上一次++后的结果
- 看到了上面的结果,对于静态变量修饰成员相信你也有了一个初步的了解,对于普通的局部变量,是存储在栈区上的。但是对于静态变量,你知道它是存储在什么地方的吗?
- 没错,就静态区,我们通过下面这张图再来了解一下在计算机内存中变量到底是如何存储的
❗内存原理图❗
- 可以看到,在静态区里,不仅仅是有静态变量,还有这个全局变量,接下去就让我们来看看【static关键字修饰全局变量】
5.2、static关键字修饰全局变量
//add.c
int g_val = 2022;
//test.c
extern int g_val; //声明外部符号
int main(void)
{
//2.修饰全局变量
printf("%d\n", g_val);
return 0;
}
- 以上的这种全局变量声明,以及【extern】关键字调用,我们在上面有讲到过,这是可以运行的,但是若这个g_val变量被定义成了静态变量,会怎么样呢?我们来看看
-
可以看到,这个外部命令无法被解析,注解中我也有写到
全局变量是具有外部链接属性的,如果全局变量被static修饰,外部链接属性就变成了内部链接属性,其他源文件就没法再通过链接找到这个符号
-
所以可以得出结论,==static修饰后的局部变量只能在自己所在的.c文件内部使用~==
5.3、static关键字修饰函数
接下去我们再来看看用static关键字去修饰函数
- 其实这个理念也是一样的,若你不使用static修饰,那你可以用extern关键字做一个引入,那它就是一个外部链接,但若是你使用static修饰,那么这个函数就只能本源文件使用,不可以给到外部的文件使用,这就是一个内部链接了
- 我们可以来试一下
- 可以看到,也是同理,这是一个内部链接,外部是访问不到的,即使是有这个extern关键字
十四、 #define 定义常量和宏
说完了操作符、关键字,内容就只剩20%了,接下去我们来讲讲【#define 定义常量和宏】
- 首先来说说这个#define去定义常量
#define MAX 100
int main(void)
{
printf("%d\n", MAX);
int a = MAX;
int arr[MAX] = { 0 };
printf("%d\n", a);
return 0;
}
- 看到如上代码,我使用#define定义了一个MAX常量,并且其值为100,在main函数中,你就可以直接使用这个常量,对它进行打印、赋值
- 然后还可以对数组进行初始化,之前在数组模块中有说到过,不可以使用变量对数组进行初始化,也就是像下面这样,这是C89中规定的
int n = 10;
int a[n];
-
我上面这种初始化方式是使用常量进行初始化,这是可以的。虽然在C99中又说了==支持了这种变长数组==,但是我们还是不要养成这种习惯,对于数组的初始化要么直接指定长度、或者是干脆不指定,但是后面要添加一个{0},否则也是不对的;再或者就是用我们这种常量的形式进行一个初始化,也是可以的
-
当然除了定义整型数据常量,其他类型也是可以的,例如字符串也可以
-
就像这样:point_down:,去打印出来的话和指定定义一个字符串常量是等同的
#define STR "abcdef"
printf("%s\n", STR);
讲完使用#define去定义常量,我们再来说说宏定义,它也是利用#define去声明的
- 下面有一个求和的函数以及宏定义求和的写法,你可以对照一下
//函数
int Add(int x, int y)
{
return x + y;
}
//宏
#define ADD(x,y) ((x) + (y)) //为了保持整体性
- 然后你一定会发现一点的是使用宏来完成求和的功能更加简便,确实是这样,但是宏其实也是有缺陷的,看到代码,我对于参数x和y都加了小括号这可以保证参数的整体性,但如果你不使用这个小括号的话,那程序在传参的时候就会出现问题了。而且宏它是没有作用域这么一个概念的,作用域我们上面有讲到过,就是一个代码、一个变量的作用返回,可在宏定义中你无法去看到这个代码的作用域。最后一点,也是最重要的一点,对于宏的话我们是无法进入其内部进行调试的,调试对于我们每个程序员来说都是一个基本技能,若是一段内嵌的代码,我们无法进去调试的话,这样就看不到计算机的运行思维,对于一些大型程序来说就增大了程序的阅读性。看了上述我所说,你应该明白了宏有哪些缺陷了
- 当然这里只是简介一下,具体的在后期学习下去还是会进行一个详细说明的。
除了求和的功能外,其实你还可以定义其他功能,例如说比较两个数的较大值,就可以像下面这么去写,使用一个==三目运算符==即可
#define MAX(x,y) ((x) > (y) ? (x) : (y))
十五、 指针
说了那么多,终于是讲到指针了,关于指针这一块,是C语言中最重要的知识点,也是较难理解的,这里给大家做一个入门,后期也会做一个详细的介绍
1、引言
- 对于指针这一块,很多同学在刚开始学习C语言的时候就听别人说起过,说指针很难很难,访问内存、取地址这些操作,既危险又难搞,所以都被吓坏了。
- 但其实呢,指针并没有你们想象中得那么复杂,用宇哥的话来说,那这个东西其实就是【纸老虎(paper tiger)】,一捅就破,只是你不敢去尝试罢了。这些东西其实都是人脑设计出来的,只要你动脑去思考,那一定是没问题的
- 浙大有一位教师,它也是教授C语言的,我在慕课上听过他的课,他说“在学习计算的时候,一定要建立一个强大的内心”,那我觉得这句话说得很好,如果你没有一个强大的内心,你怎么去应对如此多繁杂的事物呢,是吧。这位老师叫做【翁恺】,大家也可以去听听他的课,感受一下如果去学习计算机
说了这么多,接下去就让我们进入指针的学习吧📚
2、内存的概念和介绍
- 对于指针这一块的话,是直接和计算机中的内存发生关系的,所以我们先来讲讲内存相关的知识,带大家先行了解一下底层的知识
- 对于内存,大家在日常生活中应该也有听到过,例如我们为电脑、笔记本买的内存条,以及我们手机的内存,对于这个内存来说,一般都是8G或是16个G,与内存相对应的,那就是硬盘,一般的话都是500G或是1个T这样
- 那了解了我们生活中的内存,那有同学就会想,这个内存在生活中我是知道了,但是在这个计算机中、在编译器中又是什么样的呢?我们继续来探讨一下
- 在计算机中呢,内存是一块连续的存储空间,但是这样就无法分配到每一个部分进行使用,这个时候呢就将内存分成了一块块小的内存单元,那为了能够有效的访问到内存的每个单元,就给内存单元进行了编号,这些编号就被称为该内存单元的地址
- 从上面这张图示,就可以很直观地看出内存在计算机中到底是如何存储的,每一个内存单元的大小都是一个字节,然后为它们都一一进行了编号,这样在外界需要访问时,就可以根据这个内存编号去指定进行一个访问,那上面说到了,这个一个个编号其实就被称为是地址
知晓了地址的基本概念后,接下去让我们到编译器中去看看这个地址究竟是怎样分部的:house_with_garden:
- 首先我们来看最简单的一句代码,就是定义一个变量a,我们都知道int整型的变量在内存中是占4个字节的,我们在这句代码上打个断点进入内存窗口一看究竟
int main(void)
{
int a = 4;
}
- 然后呢输入这个【&a】,就可以看到内存中为变量a开辟的4个内存单元,首地址就是从【0x0052FBC4】开始,整型变量占4个字节,看我框起来的这4个就是,对于每一个字节它都有自己的一个编号,&a呢就是取到第一个字节的地址
- 那我们要怎么使用代码去获取这个地址呢,看,就像这样
&a //拿到的值第一个字节的地址
- 我们通过调试窗口再来看一下。很明显,得到了我们想要的结果
- 或者你不想到调试窗口中去看的话,也是可以的,我们直接printf打印出来即可,可以看到,这里使用的是%p,这是专门对于地址访问的,如果你是%d,出来的就是格式化后的数字了
- 讲完了内存,讲完了地址,接下去才是真正的指针,但其实对于地址来说,它就是指针,指针是地址的一个别名,下面就来看一下指针是如何去定义的
int a = 4;
int* pa = &a;
- 可以看到,在int类型后我加上了一个【*】星号,这就说明这是一个指针类型的变量,这个pa就是【指针变量】,因为上面说过==指针是地址的别名==,所以这个等式是成立的,pa这个指针变量可以去接收a的地址,也存放了a的地址
- 那如果你还是不太懂的话我画了一张图,希望你通过这张图能够对指针变量存放地址有一个理解:mortar_board:
- 那对于这个指针变量,难道只能存储整数的变量。当然不是,若是你要存储一个char类型的数据,这时候只要把指针变量的类型从【int*】改成【char*】就可以了,就像下面这样。那如果你对这个都理解了,那上面的也不会有问题
char ch = "w";
char* pc = &ch;
博主拍了拍你,问了你个问题说:既然这个指针变量存放了变量的地址,那么可不可以通过这个指针变量去访问到这个地址并且把它打印出来呢?答案是可以的,这就是涉及到我们的下一个知识点,就是指针的==解引用==
- 那这个解引用怎么操作呢?就是利用【*】这个操作符,这个我们前面说要放到指针这里来讲,现在我们就来说一说,这个星号,其实不仅是作为定义指针变量的符号,也可以将它叫做【解引用】操作符,例如下面这样
*pa
- 上面定义了,pa就是一个指针变量,*pa其实就是通过pa中存放的地址,找到这个地址所存放的空间,这个时候取到的其实就是变量a,因为取到了这个地址,这块空间上所存放的起始就是a变量的内容,我们通过运行来看一下
- 从上述运行图可以看出,&a和指针变量pa的地址是一样的,这就印证了我们最初的说法,==指针变量里存放的是变量的地址,然后*pa解引出来就是变量a中存放的内容==,通过a的地址成功地找到了a这块内存空间
小结
- 通过上面一系列的叙述和讲解,你对内存、地址、指针这三块之间的关系有没有一个初步了解了呢,我们来总结一下
①指针其实就是地址,地址就是内存单元的编号
②把地址进行存储的时候,就可以放到一个变量中,这个变量就是【指针变量】
③我们说的指针,实际上在专业术语中叫做【指针变量】
④【*】星号解引用可以通过存放变量的地址快速访问到那个变量在内存中所存放的位置,继而获取内容
3、指针变量的大小
我们都知道,每一个变量都是有大小的,它们在内存中的大小取决于它们的变量类型,如果你忘记了,可以再翻上去看看,但是对于指针变量,它有大小吗?我们来探讨一下
- 求一个变量的大小,你还记得用什么吗?没错,就是sizeof()这个关键字
int a = 10;
printf("%d\n",sizeof(a));
printf("%d\n",sizeof(int));
- 上面这段代码的打印就是4 4,那请问下面这段呢?
int a = 10;
int* pa = &a;
printf("%d\n",sizeof(pa));
printf("%d\n",sizeof(int*));
- 很明显,也是4 4,你算对了吗。
- 在编译器的偏左上角,有一个x64和x86,这个东西叫做【运行环境】,x64代表你在64位OS的环境下运行代码,x86代表的就是32位,刚才我选择的是32位,现在我把它改成64位,你觉得会发生什么变化?我们一起来看一看
- 很明显,一样的代码,但是在不同的运行环境下所产生的值却不通过,这是为什么呢?那这个时候就有同学迷茫了,这个指针变量的大小到底取决于什么呢?
- 这个时候其实又要追溯到地址这一块的知识了,为什么又要牵扯到地址呀!!!
- 因为指针变量存放的就是地址,所以指针变量的大小取决于==存储一个地址需要多大的空间==
要看到不是地址,其实是存储的地址线,没错,就是硬件上的地址线
- 我们所用的电脑,其实就是硬件,是硬件的话就需要通电,那在我们的电脑上其实就存在着这么一种【地址线】,我们上面所说的32位与64位,也可以对应到这个地址线中,因为在32位的环境下,是32根地址线;64位环境下就是64根地址线
- 当我们是32根地址线时,在通电之后就会有一个电信号,这个电信号就是0/1,那这些电信号具体是怎样的呢,我们来看一下
- 就是0101这样的存储方式,然后根据二进制的逢二进一去罗列出这32根地址线可以存储下多少地址,这里告诉你,一共是有2^32^个地址可以存储
- 那这其实就可以得出结论了,32个0或者1组成得的地址序列,需要32个bit,也就是4个byte去存放,而这4个字节也就对应着我们指针变量的大小,因此就可以得出为什么指针变量的大小是4个字节了
- 然后来解释一下为什么在64位环境下这个指针变量就变成了8个字节,这其实你自己也可以去推导,32个0或1组成的地址序列需要32个比特位,那么这里便需要64个比特位,根据1B = 8bit,所以就需要8个byte去存放,这也可以得出在64位环境下指针变量的大小是8个字节
了解了上面这些,知道了==指针变量的大小取决于地址的大小==,下面我们来看看这些指针变量的大小是多少,我是在32位环境下运行的
printf("%d\n", sizeof(short*));
printf("%d\n", sizeof(long*));
printf("%d\n", sizeof(long long*));
printf("%d\n", sizeof(float*));
printf("%d\n", sizeof(double*));
- 是1 4 8 4 8 吗,如果是这个答案的话请你再回去仔细看一下上面的推导过程
- 我们来看一下运行结果
- 可以看到,均为4,为什么呢?因为它们都是指针变量,只要是指针变量那么求它的大小看的是什么,没错,看到就是地址的大小,上面说了,我是在32位环境下运行的,因此就是32根地址线,需要32个bit,也就是4个byte去存放,继而退出这个指针变量的大小是4B
接下来给你看个很细的东西
- 首先肯定不是这个字,而是这个【%d】,为什么要说这个呢,给你看一下我运行后的结果过,可以看到,报了很多Warning,这是为什么呢,明明这个代码就是可以运行的,而且还可以出结果
- 但是能出结果的代码就一定没问题吗?这个见解可不对,你要自己分析或者看编译器给你报出的问题。可以看到,这里报了一个【符号不匹配】的问题,为什么呢?这里明确说一下,sizeof()计算数据字节大小的时候默认返回的类型是unsigned int,也就是无符号整型,但%d是用来打印整型变量的,所以这里才会出现【符号不匹配】的问题
- 那这该怎么改呢,应该将其修改问%zu去打印才对,你只要记住它是==专门用来打印sizeof()的返回值==的就行了,不行深入了解也没关系
- 修改如下,可以看到,已经一个Warning都没有了
十六、结构体
OK,终于是到了最后一个模块,对于结构体,也是C语言中比较重要的一个部分,因为C语言是一门面向过程的语言,它不像C++、Java那样面向对象,具有类,可以在类内定义成员变量和成员方法,所以C中就有了结构体这一个东西,可以用来==描述复杂对象==
- 我们都去书店买过书,知道书它有书名、出版社、作者,这些都可以定义为字符类型,但是还有书的价格,怎么定义呢,难道也定义成字符类型吗,当然不是,依旧是定义成浮点类型,除了这些,其实还有很多种类需要去定义
- 但是对于这么多的类型,都要分开吗,这肯定不行,这样这本书就不是一个整体了,如果你有面向对象的思维就知道,它的属性和行为都是定义在这一个类中,都是封装好的,这就是类的封装
- 在C语言中,我们也可以实现封装,那就是用结构体
我们以学生类型来做一个封装
- 可以看到,我们使用到了struct这个关键字,这个就是在关键字那一模块所属要留在这里讲解的关键字,stu就是student的简写。可以看到,里面有着三种类型,分别是姓名、年龄和成绩,因为一个学生都具备这三种属性,这是他们共同的属性,所以可以将他们封装在一起
struct stu {
char name[20]; //姓名
int age; //年龄
float score; //成绩
};
- 那对于结构体这种复合类型怎么去定义变量进行初始化呢,我们来看看
- 其实和普通变量也是一样的,你要把【struct stu】看做是一个类型,用这个类型定义出来的变量就叫做【结构体变量】,对于每个结构体变量的初始化,都需要使用一对大括号{},里面去一一按照顺序去初始化你在结构体中定义的变量
- ==温馨提示:这里的float成绩类型后面加上f与double类型作为区分==
struct stu s1 = { "zhangsan",20,80.5f };
struct stu s2 = { "lisi",25,90.5f };
那初始化了这些变量后如何将他们打印出来呢,也就访问到每一个同学的信息
- 这里就要使用到【.】点操作符,这个也是我们前面留下的,这个操作符可以去通过结构体声明出来的变量访问当前这个变量所具有的信息,代码如下
//格式:结构体变量.结构体成员
printf("%s %d %f\n", s1.name, s1.age, s1.score);
printf("%s %d %f\n", s2.name, s2.age, s2.score);
拓展
再来做一个拓展,看看你对上面的知识是否真的掌握了,会涉及到函数、指针、结构体哦📕
- 现在我要将打印学生信息这个功能封装成一个函数,之后我只需要调用这个函数就可以实现学生信息的打印,不需要再写printf了,请你实现一下
void Print(struct stu* ps)
- 首先我问你【struct stu*】是什么,没错是个指针类型,什么类型呢,【结构体指针类型】,这个ps是什么,就是指针变量,前面说到,指针变量可以存放变量的地址,并且需要同种类型的,那我在main函数中声明出来的结构体变量可以直接传给这个函数做实参吗?
- 当然不可以,你还要加上【&】取址符,这个时候指针变量接收的就是一个变量的地址,然后在Print函数中,我们通过这个指针就可以去访问这个变量所存储的内容,代码如下
Print(&s2);
printf("%s %d %f\n", (*ps).name, (*ps).age, (*ps).score);
- 这就是我们刚才所说的【解引用】操作符,它在结构体中依然适用
- 我们还有一个操作符没讲,你还记得吗,就是【->】这个箭头操作符,这其实才是指针所需要使用的操作符,无需解引用,直接用箭头就可访问
- 代码如下,很直观明了:point_down:
//格式:结构体指针->结构体成员
printf("%s %d %f\n", ps->name, ps->age, ps->score);
- 最后一个,对于结构体声明的变量,难道只能在定义的时候初始化吗,可不可以自行输入?当然是可以的,格式与普通的变量输入也是一致
scanf("%s %d %f", s2.name, &s2.age, &s2.score);
- 细心的同学可能发现了,对于名字为什么没有&符号去输入,你在仔细看一下name我定义的是什么,是一个字符数组,我们有讲到,数组名其实就是首元素地址,那这已经是一个地址了,为什么还要再去取地址呢,是吧,对于数组类型的话,无需【&】,直接输入即可
十七、总结与提炼
以上十六个大点,就是我罗列出来的C语言中一些较为重要而且必须掌握的知识点,可作为一些刚入门的同学进行一个整体性的了解
- 回顾一下所有的知识,一开始我们首先使用VS2019编译器写了我们第一个C语言程序,出入了解了C语言如何去进行编程🐏
- 接着我们了解到一些基本的数据类型,有char、short、int、long、long long、float、double这些
- 知道了C语言中有常量与变量,并且清楚了它们的分类
- 再者了解到了字符串相关的知识,知道了如何去求解一个字符串的长度。然后又知道了有注释这么一个帮助理解代码又可以暂时隐藏代码的东西😀
- 又然后呢进入了选择语句和循环语句的学习,了解了面向过程如何去实现
- 学完这些后开始了解函数,知道了可以将一些功能单独封装为一个模块进行后续的调用
- 有了函数,那一定少不了数组这个存放大量数据的东西,也方便了我们对于数据的访问和存放
- 各种操作符和关键字看得眼花缭乱😵,但是又不得不讲的很仔细,生怕大家听不懂
- 然后呢了解到了#define去定义常量和宏,要注意不可以滥用哦,可以有缺陷的❗
- 又爱又恨的指针出现了,地址、内存与指针之间的联系还记得吗,忘了就再上去看一遍吧
- 最后的舞台当然是留给结构体啦,封装好所有的数据,就想一个大房间,大家都可以住进去🏠
好,讲到这里,我们初识C语言的内容就全部结束了,本文大概是用了4万多个字讲解了C语言中一些较为基础也是较为重要的知识点,本文仅作为初学阶段的入门了解,并不能作为深入地理解C语言的各方面知识。最后,希望这篇文章对您有所帮助,可以大致地了解到C语言到底会学些什么知识,在编程之路的行走不再迷茫
- 点赞
- 收藏
- 关注作者
评论(0)