前言:
兜兜转转,经过较长时间的学习、总结出一篇C语言的那些少见的事,各位看官久等了。
1.变量名称的意义
在创建变量的时候,我们通过都被要求起个名字。大家可能不太清楚这个名字的的作用是什么,而只是知道拿起变量名,该怎用就怎么用。
实际上,变量名是方便我们程序员自己的一个标签。这是为什么呢?首先我们需要知道的一点是:计算机进行操作时,是找到相应地址,对地址内存储的数据进行更改,计算机才不管你给变量起什么名字,名字起的好与坏,是程序员容不容易理解的问题。
我们只需要知道,变量名称标识了一块内存空间,使用变量名,就是在对相应的内存块进行操作,我们不必知道计算机是如何寻址找到那块空间的。
这时候有小伙伴会问?博主那有没有什么办法,既不要给内存空间起名字,又能使用这块内存空间呢?答案是可以的。和往常一样,首先你要向操作系统申请内存空间,第二就是返回指向这块内存空间的指针。
一般这种情况都是在动态内存开辟的时候使用动态内存分配函数malloc、calloc、realloc开辟堆区上的空间,这些函数会返回指向开辟空间的指针,并且这块空间没有名字。
2.卖函数库的知识
在我们掌握了编程的知识后,我们将一些在工作时可能用到的函数,并且库函数里没有,封装在一个自己实现的库里面,将这个库卖给需要的买方。当然这个库实现的功能要足够的强大才有人买(doge)。
这里博主给出一个流程,大家看完之后可以去实现一下,方便日后将自己的能力变现:
写出函数的.h文件和.c文件
.h文件放的是函数的声明、.c文件放的是函数的定义(实现函数的文件)。由于我们卖库并不想把我们实现函数的思路和代码卖出去,我们需要将声明和定义分开来,这种方法不仅能让买方无法得知我们如何实现函数的;
补充:还有的好处体现在工作的时侯,需要分工协作完成一个项目。我们不可能都在同一个.c文件里写函数,也不可能说,你先写完你那部分的功能,我再打开.c文件写我负责的那一部分。所以每个程序员负责的模块都自己写一个.h和.c文件,到最后包含头文件(相当于包含声明)放在一个文件里,将各种函数的实现组装在一起完成任务。
改变项目的属性配置
调整完成后,ctrl+f5运行起来会生成相应的.lib文件在相应的路径下。
这里会报错,不过没关系,这只是因为我们没有用main函数生成可执行程序而已。然后就到相应的路径下查看.lib文件,用记事本打开你会发现里面全是乱码,这是因为它已经是二级制文件了。
将.lib文件和.h文件出售
因为.lib文件是看不懂的,所以买方根本不知道这里面有什么样的函数,我们顺带把.h文件也卖出去,相当于是.lib库使用的说明书。.h文件里面包含着.lib文件里的各种函数声明以及函数的返回类型、函数名、参数、功能描述等。
买方买到后如何使用静态库(.lib)
在编译器头文件里添加现有项.h文件
添加完之后,要引用头文件,也就是包含函数声明。并且要用一句代码导入静态库,就可以使用啦~
成功啦!以上就是一个过程~
补充:自己的头文件用""(双引号),库的头文件用<>(尖括号)。区别在于,""包含的头文件,编译器先在本地里找文件,找不到再去C库(编译器软件里实现函数的文件)里找。<>包含的头文件,编译器先在编译器软件里找,找不到再到本地里找。
3.变长数组
C99中规定,可以允许我们使用变量当做指定数组元素的个数。如果编译器支持C99标准的话,我们可以实现下面的表示:
int main { int n = 10; int arr[n]; return 0; }
其中n是变量,还有一点需要注意的是,变长数组不能进行初始化。
4.清空输入缓冲区
清空输入缓冲区,可以使用循环getchar()将输入缓冲区里的内容逐一全部清空,具体实现如下:
int main() { while(getchar() != '\n') { ; } return 0; }
因为不需要这个循环具体做什么事情,所以我们在循环体里放的是空语句。getchar正常读取返回读取到的字符对应的ASCII码值,读取失败返回EOF。scanf正常读取返回读取成功的个数,读取失败返回EOF。
另外还可以使用fflush(stdin)函数清空输入缓冲区,但在VS上这个函数的功能被取消了。
冲洗stdin(standard input),清理标准输入流,这样会好记一点。
5.左值和右值
左值和右值的意思分别是:左值是一块空间;右值是一个数值、空间的内容。
#include <stdio.h> int main() { int a = 10; const int b = 8; a = 20;//a是左值,b是右值,a代表的是可以存放整型的内存空间 b = 10;//error,这个时候编译器会报错---左值不可被修改 //因为const修饰的b变量它这块空间里的内容是不能被改变的 return 0; }
6.for控制语句中定义变量
在C99标准中,支持在for循环控制条件初始化部分定义变量。
#include <stdio.h> int main() { //C99标准支持这样创建变量i for(int i = 10; i >= 0; i--) { printf("%d ", i); } return 0; }
7.刷题中浮点数的精度问题
在使用牛客网或力扣进行刷题的时候,往往对于浮点数并没有明确要求使用float还是double类型,float和double的区别是它们所占空间大小不一样,所以对于精度的存储也不一样。
如果对于精度这方面有能力直接看出来的,就用表示对应精度的类型就ok。如果不行我们就让两种类型换着去解题也是可以的,也就是float的精度不能很好匹配就用doubel、或是精度太高了我们就返回去使用float类型。对应double类型的输入输出格式是%lf。
int main() { float f = 3.2;//在VS下,3.2虽然是单精度的表示 //但编译器仍看成是double的类型,可以在3.2后面加上f表示是float类型 float c = 3.2f;//这样就不会有double向float类型装换,精度丢失的警告了 return 0; }
小数3.2在VS编译器下默认是double类型。
8.C语言提供C的标准和C库的约定
我们在使用库函数的时候,经常说函数是C库提供的。实际上,函数的定义并不是由C语言函数库直接实现的,而是由编译器的厂商实现的。比如VS、GCC编译器实现scanf函数。
C库只规定函数的功能、名字、参数和返回值。各大厂商根据这个标准去实现库函数,即使在不同编译器中,内部实现库函数的方式可能略有不同,但使用起来的效果是一样的,这就是因为C语言提供了标准形成的局面。
9.extern声明外部符号
在学习关键字extern的时候,extern是用来声明外部符号的。
然而我们并不一定需要用加extern来声明外部符号glo_bal、Add也可以正常使用的。
结语:希望读者读完有所收获!在学C的路上,祝福我们能越来越C!✔
读者对本文不理解的地方,或是发现文章在内容上有误等,请在下方评论区留言告诉博主哟~,也可以对博主提出一些文章改进的建议,感激不尽!最后的最后!
❤求点赞,求关注,你的点赞是我更新的动力,一起努力进步吧。