0基础C保姆自学 第二节——初步认识C语言的全部知识框架
Posted jxwd
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了0基础C保姆自学 第二节——初步认识C语言的全部知识框架相关的知识,希望对你有一定的参考价值。
大家好,我是@jxwd(健祥无敌~~~~哈哈)
写在前面
各位小伙伴还在为C语言的学习而苦恼嘛?
还在为没有知识体系而烦心嘛?
别急。因为~~~~
接下来的两个多月,我会持续推出C语言的有关知识内容。都是满满的干货,从零基础开始哦~,循序渐进😀,直至将C中知识基本全部学完🐂。关注我♥,订阅专栏 0基础C语言保姆教学,就可以持续读到我的文章啦😀🐕~~~~
本文为万字长文,满满干货。为防止找不到,可以收藏再看呦😀
本文为第二节~~~
文章在看本章节前,请确保已经掌握了第一节的内容呦。不懂的欢迎在评论区留言~~~~
jxwd,让你服气,拒绝水文,从我做起!
本节定位:初步了解认识一下C中的知识,所有的知识都是点到为止。
目的是能够看懂别人写的代码,不要求自己能够写出非常标准的代码;是在接下来章节的介绍中笔者的举例读者可以更好的接受。比如在函数的介绍中我们会用到指针。
所有的知识点我们都会在接下来的章节一一详细介绍
所以,读者在阅读本章的时候,只需要知道有这么个东西,并且能够理解笔者所说的含义即可。
本节我们将沿着上一节介绍:
本节内容有:
目录
10-9-1 ! 逻辑反操作 (很简单,就是如果语句为真,那前面加上!语句就变成了假)
注:上述带*的内容可以不用在本节掌握,读者可以在这里当作一种视野拓展,以满足读者的好奇心。
C语言除了以上内容,笔者还会给大家介绍
文件操作 和 编译链接。
但这两部分比较复杂,我们本节不提。如果想看,欢迎订阅专栏,关注@jxwd,这样就能第一时间看到我更新的文章啦。
(虽然是万字长文,而且有二三十张配图,但我敢说没几个人能认认真真从头看到尾😀)
话不多说,我们开始。
还记得我们在上一节输出了第一个C程序,那么,读者应该掌握C语言的基本程序框架。
当然,如果不记得了,我们可以在这里再次重复一下。用一张图片来表示就行,如下图:
1、 数据类型
数据类型是固定大小内存的别名
常见的数据类型有哪些呢?
char 字符型
int 整形
long (int) 长整型
long long (int) 更长的整形
short (int) 短整型
float 单精度浮点型
double 双精度浮点型
注明一下:在这里,可以通俗的理解:
①字符型为键盘上能敲出的任意一个单个字符。
②整形为正数,浮点型为小数。
那这些类型是干什么的,怎么用呢?(建议初学者讲笔者所有的代码在自己的编译器上自行操作一遍。实操很重要!)
1-1 数据的创建
像这样,我们分别将上述每一个类型都创建了一下,并且将其初始化了。所以,像上述的创建方式,可以总结为: 数据类型名+ 自定义类型名,给它赋了一个值(这里的10.2f仍然是一个数,我们下面会讲)意为给它初始化了一下。
1-2 数据的打印
我们来看下面一段代码:(为了使读者得到更多的练习,笔者在此尽量以截图的形式来呈现代码)
代码敲完后,按ctrl+(fn)+f5
如图,我们将上图的六个数据打印出来,得到了相对应的六个数据。
我们发现这样几个规律:
①在printf函数(即打印函数)中,都是以类似于(“%() ”, );打印出来的。
②每一行的类型不同,打印时%后面跟的字母也不相同。
③每一个printf中都含有一个'\\n',它表示换行。(否则,打印出的形式将会是如下的形式:)
很挫是不是。。。。。。。
我们提一下%后面的字母是什么意思:
在C语言中,打印类型需要遵守一定的规则。就是在打印前需要先告诉编译器你打印的是什么类型。%d代表我后面要打印整形;%hd表示我后面要打印short类型;%f表示我后面要打印float类型....其他类推。
在前面告诉完编译器要打的类型后,还要再在后面写入要打印的变量名字(就是说要打印谁的值)
附:部分%后面跟着不同字母的不同含义:(如果读者对部分不理解可以先放一放)
%c | 打印char (字符类型) |
%d | 打印int(整形) |
%f | 打印float(单精度浮点型) |
%lf | 打印double(双精度浮点型) |
%p | 打印地址 |
%s | 打印字符串 |
%u | 无符号的十进制形式打印整形 |
%x | 以十六进制形式打印 |
%o | 以八进制形式打印 |
1-3 数据的大小
每一种类型的数据的大小又是多少呢?
我们用一个C语言中的关键字:sizeof来实现这个功能。其中sizeof的含义是求某个数据类型所占空间的大小,单位是字节。比如sizeof(int)就是指int 的数据所占的内存大小。
我们来看下面一段代码:
如图,我们可以看到,char类型的大小是1个字节;short类型的是2个字节;int 类型的是占4个字节;float也是4个字节....(注:long在有的编译环境下不是4个字节,而是8个字节)
在这里,我们需要补充一个硬知识:
计算机存储数据示意二进制的形式存储,每一个0或者1占据一个比特位。
一个字节=8个比特位;
一个kb=1024个字节;
一个MB=1024个kb;
一个GB=1024个MB;
一个TB=1024个GB;.......
而在我们上文中所说,int占4个的是字节,char占1个的是字节....
这样说,可能对于字节的大小理解得更加深刻点吧。。。。。。
好,关于数据类型就先给大家介绍到这里,大家只要会创建、会打印,知道它们占据空间的大小就行。
2、常量和变量
第一个问题还是要问:
什么叫变量?
· 变量,顾名思义就是可以改变的量。
像我们上面所说的创建的变量,即a,b,c,d,e,ch,它们都称之为变量。
因为它们所表示的值都可以改变。比如,我可以让a+1,也可以让b-1,让c等于50等等。这个并不难理解。
2-1 变量的分类、作用域和生命周期
变量分为:局部变量和全局变量。
2-1-1局部变量:
定义于局部的变量。
这里的局部指的是在函数的内部中声明的。例如:
左上图中, 这里的a定义于main函数的内部,可以认为,它是一个局部变量。
同样的道理,在由上图中,我们的add是一个函数(函数具体的细节我们后面讨论,现在知道它是一个函数)中的b也就是一个局部变量。
2-1-2 全局变量:
作用于整个项目的变量。
例如:(如下图)
这里的c就是全局变量。 在全局范围内定义的变量。
局部变量和全局变量类似于整体和局部的关系。
当局部变量和全局变量的名称冲突时,局部优先。(相当于局部又重新定义了一次)
例如:
看,打印出来的就是20。
因为在printf这个地方,局部的a是优先于全局的。
2-1-3 变量的作用域和生命周期
1、对于全局变量来说,变量的作用域为整个项目工程,生命周期与项目的执行周期相同。
2、对于局部变量来说,其作用域为其所在的整个函数,生命周期为其所定义之时起,至函数运行结束后终止。(函数运行结束后,该变量所会被销毁,所占用的空间会还给内存)
我们通俗的说一下,全局变量在整个项目运行的过程中一直存在,并且一直可以用。但是全局变量在出了所定义的它的函数之后便销毁,便不再存在。
2-1-4 变量的使用
我们以输入输出来学习变量的使用。
我们来完成这样一个任务:
输入两个数,并打印这两个数。
我们把样例代码给出,读者可以自行去打着试一下:
读者可以看到,我们在这里引入了一个新的函数scanf。
scanf函数是一个输入函数,用于输入数据。它的用法与printf相似,类似于(“%() ”, );但是有的读者已经注意到,我们在变量的前面加了一个&。它在这里的意思是取地址,原因是我们输入是要对变量a,b所在的地址进行输入。如果不加上这个&,编译会报错。
打完代码后,我们按住ctrl+(fn)+f5,让代码运行。
我们在控制台输入3 2(注意两个数字间有一个空格)
然后我们可以看到,在屏幕上输出了两个数字3 2。(输出中间之所以有空格,是因为第一个%d后面我们加了一个空格)
这就是标准输入输出!
关于scanf会报错(注意是报错不是报警告)如何解决,推荐大家看一个视频介绍,看完后就知道该如何解决了。
【C语言学习问题】VS2013编译器对函数不安全报错的解决办法_哔哩哔哩_bilibili
那什么叫常量呢?
2-2 常量
常量,是指在给出值以后,不可以再被修改的量。(注意:这里我们所说的值是一个广泛的概念)
2-2-1 常量的类型
在目前的阶段,我们接触到的常量有如下四种类型。
1、直接定义的数值常量。
2、const 修饰的常变量。
3、#define定义的常量。
4、枚举类型常量。
我们接下来举几个栗子:
第一种:直接定义的数值常量。
像这样,10表示一个数值常量;而字符‘a'表示一个字符常量。它们都是我们直接定义的数值常量。
第二种:const 修饰的常变量。来看:
像这样,前面由const修饰的变量a,就变成了常(变)量。常变量保留的变量的某些特征,但是它具有的常量的性质,其值不可以被修改。
在普通情况下,我们均将其当作一个常量。比如,我让a+1,然后重新复制给a,这个时候,编译器就会报错:(如下图所示)
第三种:#difine定义的常量:(就是我们所说的宏常量)
例如:(如下图)
在这里,MAX就是一个常量,它的值为10。如果打印出来,可以看到,控制台上显示的为10:(如下图)
同样的道理,如果将其值修改,我们会看到编译器会报错。
第四种:枚举类型常量。
对于枚举类型,我们要用到一个关键字enum,即通过enum来将常量一一列举出来。来举一个栗子:
从上面我们可以看出,我们在枚举类型中给出所要给的量的名称(我们这里列举的是男,女,保密,当然,你想列举什么就列举什么),那么它们就将成为常量;
*(它们的值默认从0开始,以此往下递增。(提一嘴,因为它们代表的值是整形,所以我们可以用%d来去打印))
注:标记*表示在这里可以不用了解,看不懂没有关系,我们在接下来的内容中会详细介绍的。
我们接着往下说:
3、数组
数组就是把类型相同的元素放在一起,形成一个的集合
3-1 数组的声明
数组的声明方式是这样的:
例如,我们可以这样声明一个数组:(如下图)
1、这里的int的意思是数组中元素的类型全部都是int;
2、array是数组名,你想起什么都可以
3、[9]表示数组中有9个元素
4、{1,2.....,9 }表示数组的元素(你想给什么都可以,但前提是元素都要是你前面所声明的类型)
3-2 数组的初始化
像我们上面那样,在声明的时候,给它的元素全部列举了出来,就是数组初始化的一种形式。
这种把数组的元素一一列举出来的初始化方式,称为数组的完全初始化。
另外一种数组初始化的方式,称为不完全初始化。
比如:
这表示什么呢?
表示数组的第一个元素为1,剩下的8个元素都是0。
3-3 数组的访问
那我怎么样才可以拿到(访问)数组的某个元素呢?
我们以上面的 int array[9]={1,2,3,4,5,6,7,8,9}; 为例:
首先,数组的每一个元素都是有下标的。而且是从零开始,然后直至最后一个元素,依次递增。如图:
那么,我们在访问的时候,是以数组元素下标的形式来访问的。
比如,我想访问数字2,那么我就可以用array[1]来访问。
那现在,我们把它打印出来:
其它的元素访问规则以此类推即可。
注意:在这里要强调一下,数组中的元素类型一定要相同。
4、字符串
字符串,字面意思,就是指字符和字符在一起形成一个串
字符串一般会用双引号引起来,而不是单引号。
比如 “abcde” 就是一组字符串。
在C语言中,没有单独的专门用来声明字符串的类型。所以我们把它放在字符数组中去声明。举个栗子:(如下图)
这便是一个字符串。
我们来分析一下:
我们可以把字符串理解为一个特殊的数组,或者就是一种字符数组。
注意:
在每个字符串的后面,其实还隐藏这一个'\\0'。
它不算到字符串的长度中,但是却占据一个单位的空间。
比如,上文提到的字符串"abcdef",它的字符串长度是多少呢?(如下图)
(如上图)
也就是说,这个字符串长度为6。
我们可以来验证一下。
验证时,需要引入一个库函数:strlen,它用来计算字符串的长度。计算的原理是从字符串的第一个字符开始,一个一个向后遍历,直至遇到'\\0'为止,计算'\\0'前面的字符个数。用它需要引头文件<string.h>
看下面的栗子:
可以看出,该字符串的长度为6。而字符'\\0'是不计入字符串长度中去的。
5、转义字符
我们输入这样一行代码:
我们让代码运行,来看一看会输出个什么样的东西
一堆乱码?
其实不是。
那为什么会输出这么个鬼东西?
这就与转移字符有关系了。
在这里,编译器在遇到’\\t‘后将其转义,不再是原本含义,而是转变为水平制表符,相当于一个tab键缩进的长度,大概相当于4个空格(多少个空格可以自己改)。
而\\102也是一个转义字符。它是102是八进制数字,它输出的为八进制数 102 在系统中所代表的ASCII码值。
\\n也是一个转义字符,它的意思是换行,我们之前提到过的。
在这里我们提一下ASCII码,它的全称为美国信息交换标准码。它实际上是一个字符-数字转换表。即我们在计算机中,给定一个数字,它在内存中其实还对应着一个字符。同样的道理,我们在计算机中输入一个字符,它在内存中其实还对应着一个数字。而其所遵循的转换的规则就是ASCII码表(注意:该数字是有范围的)。现我们把ASCII码表给出
\\102转换为十进制就是8^2+2=66,而在上面的表中我们可以看到它所代表的字符为B
好,我们再回到转义字符上来。
这就是相关的字符相关的转移。
当编译器遇到\\a时,电脑会响一下,\\b表示退格,\\f表示换页...重点需要注意的时\\n; \\t; \\ddd;\\xhh;
\\n表示换行;\\t表示水平制表符(相当于一个tab);
需要指出的是,\\xhh指的是打出\\x后再在后面加两个十六进制数所对应的值;而\\ddd则表示\\后面加三个八进制数所对应的值(我们刚刚提到过)
那么,我们就可以解释一下刚刚为什么打印出来那么一堆乱七八糟的东西了
其中,转义字符算一个字符。
那好,我们看一下下面的这一串字符的字符长度是多少:
\\1133\\138\\test\\\\.c\\n
答案是12;你算对了吗?
为什么是12?
根据我们上面说的,
需要注意的是,我们没有把\\138放在一起。因为\\ddd是八进制,数字只能有0~7,是不能有8的。
好,转义字符我们就说到这。
6、代码注释
先行的代码有两种注释方式。
第一种,是C风格的注释方式:用/* */;
第二种,是C++风格的注释方式,C99后流行,用 \\\\;(如下图)
当然,/* */这种注释方式是有一定的缺点的:即不可以嵌套。请看:(下图)
我们先把main函数里面的注释掉,再想在外面注释的时候,我们发现,后面的括号并没有被注释掉。
7、函数
函数是C中最重要的一个部分。可以说,一个程序是由若干个函数组成的。那么函数到底是什么?它到底怎么用?我们今天在这里先稍微地提一下,读者只需清楚什么是函数就好,我们今天只是简单的介绍一下,不深入,不发散。
首先,函数有两种,一种是库函数,一种是自定义函数。
我们用的printf;scanf;strlen都是库函数,也叫内置函数。包括我们常常提到的main也是一个函数。可以这么理解,库函数是别人为你写好的,然后打包封装到像<stdio.h>这样的头文件中去。你用#include表示包含这个头文件,那么你就可以去用这个头文件中定义的所有函数。
我们再来讲讲自定义函数:
我们想要用一个函数,只需要把函数的名字写出来,然后打上括号,把函数的名字写进去就行。就像这样ADD(a,b)。我们将在下面的实例中给大家演示:
现在,
我们来写一个最简单的函数——相加函数,就是把两个函数加起来。
我们先把主函数(main)写出来:
ADD(a,b)就是函数调用的意思。也就是说,我要调用这个函数,经过什么过程和操作我暂时不关心,但结果是通过这个函数,我把我传进去的a,b两个数加了起来,得到了它们两个数的和。然后我用sum来接受这个ADD函数返回来的和。(也就是这个值)
上述所描述的就是函数的调用。再说的直白一点,就是用了函数的方法。
那么,我们现在再来看看如何实现这个函数:(也就是得到这个值所经历的过程是什么)
函数实现的基本架构是这个样子的:
我们仍然以上面的函数为例:
上面的函数我们可以写成:
int ADD(int a,int b)
{
int c=a+b;
return c;
}
这样,我们就实现了这个函数。
我们先来讲讲这每一部分都代表这什么:
好,我们再在整体的代码中来看一遍,将代码怎么执行的说一遍。
所以,打印出来的值应当为30。
需要说明一下的是,我们最好把要用的函数写在main函数的上面。因为如果写在main函数下面,编译器在调用这个函数之前并没有见过这个函数,这样就会报错或者报警告。除非在前面进行一下声明。就像这样:
也是可以的。
好,就此打住,函数我们今天就了解到这。 读者只需要了解函数是什么,怎么创建的就可以。
8、选择语句
选择语句,一般来说有switch和if两种比较常见的选择语句的形式。我们今天还是点到为止,只介绍一下if的选择语句。
if选择语句的基本结构是这个样子的。
这里的else if也不一定要有,如果只是A和B中间的选择,直接用if else就行。
我们现在来举一个简单的栗子:
各位认为打印出来的是haha还是hehe?
我们来把代码运行的流程演示一遍:(如下图)
如果用流程图表示,好像是这个样子的:
ps:如果按照标准,输出框应该用平行四边形画,但我的画图板好像找不到平行四边形。不过无所谓,凑合着看吧😀,明白意思就行哈。
那我现在给两个数,然后比较出一个较大的数输出在屏幕上,可以怎么弄?
很简单,可以这样实现:
这就是选择语句。
9、循环语句
如果我想输出10句hello world,难道我要打10个printf吗?有没有更好的办法呢?
答案是肯定有的。这个时候,就可以借助我们循环语句的功能来实现。
先说一下,循环语句体中,共有三种主要循环方式,分别是for循环;while循环;do while循环。今天在这里,由本章的定位所决定,我们只是简单了解一下它们,我们只简单的介绍一下while循环(还有一个原因就是如果今天都讲了以后就没有内容写了呜呜呜~~~~~)
while循环的框架时是这样的:
来看这么一条代码:
这就是循环语句的功能。这里我们用的就是while循环。while循环的循环过程是这个样子的(我们用上图的例子来分析)
所以说,循环就是重复的执行一件事情,直至满足了某些条件,才可以跳出循环。
我们关于循环目前就先了解到这里。
10、操作符
什么叫操作符?
它就像预设好的一个操作符号,我用了这个符号,我就能实现某种目的。
听着可能有点抽象。
我们用具体的操作符来解释:
10-1 下标引用、函数调用和结构成员
主要是指 [ ] ( ) . ->这四种。
我们先讲一下前两种,后两种我们放在底下的结构体知识里面来说(往下翻,在下面讲到)。
[ ]主要用于数组中;
( )主要用于函数中。
比如,我们上面在说数组时数组的访问是通过array[2]来实现的,这里的[ ]就是下标引用,可用于数组访问。
同样的道理,我们在说函数的时候讲到写一个函数的名称然后在后面打括号,这里的括号就是我们所说的操作符。
10-2 算术操作符
+ - * / %
这个就是普通的 加减乘除 取模 。提一嘴,%表示取模。就是取余数。
比如5%2=1;需要注意的是,%不可以用于小数的运算,只能用于整数(用专业的话说,只能用于整型)
10-3 移位操作符
<< >>
我们之前介绍过,数据使用二进制存储,一个0或者1占据着一个比特位。而且一个整型有4个字节(32个比特位)。那么, << 和 >> 是在二进制上进行的操作,其中<<代表左移,>>代表右移。
我们举个栗子来说明一下:
这是怎么一回事?这操作符到底怎么用?我们来详细介绍一下:
同理,>>表示向右移位。<< 或 >> 后面跟上几,表示移动几位。
有关其它的细节,我们以后再聊。读者在此只需知道它们是什么意思就行。
10-4 位操作符
& ^ | ~
它们仍然是对数字的二进制位上进行操作的。
其中&位按位与;|表示按位或;^表示按位异或 ; ~表示按位取反。 (前面都是对两个数操作得到一个新的数,而 ~ 是对于一个数进行操作的)
什么意思呢?
我们以1表示真,0表示假,那么:
&的规则:两个数的某一位都为真,得到的这一位才是真。
|的规则:两个数的某一位只要有一个为真,得到的这一位就是真。
^的规则:两个数的某一位相同则得到的这一位为假,相同则得到的这一位真。
~的规则:一位一位看,真变假,假变真。
是不是很抽象不易理解?
那好,我们来分别举个栗子:
我们现在来分析一下为什么这样的数:
首先分析1&2:(如下图)
同样的逻辑分析1|2:(如下图)
那么1^2呢?
我们还是以刚刚说的数为例:
转换为10进制后就是3
最后一个,~呢?
这个其实很简单的,不用画图都能说明白。
还是上面那个例子:
2的二进制数为 00000000 00000000 00000000 00000010;
对每一位取反为11111111 11111111 1 以上是关于0基础C保姆自学 第二节——初步认识C语言的全部知识框架的主要内容,如果未能解决你的问题,请参考以下文章 (计算机组成原理)第二章数据的表示和运算-第二节7:详解C语言中的强制类型转换