前言
上一篇博客泡泡猪带大家干向了第一个程序,没有看过的一定要记得去仔细的观看哦,非常重要。
本 篇 博 客,泡泡猪将带大家对C语言做一个基础的概括和语法内容,也就是简单的先学习一下,这里并不会深入地去讲解。
可能在进行简单的学习之后, 我们也是能够大致地看懂其他大佬的C程序了,这对于自学的人来说应该是非常有帮助的。看完之后如果不懂,请关注泡泡猪,以后每一个知识点会分开仔细的讲解。
而且泡泡猪给出的简单明了的学习大纲会让我们更有目标地去学习。
制作不易,恳请赏个小心心
学习大纲如下:
存储器与CPU的关系
在了解存储器与CPU之间的关系之前,
我们先了解一下电影是如何在计算机上运行的
某部电影它本身是放在计算机的硬盘中的,在我们用计算机看电影的时候,首先会双击这个电影,“双击”是操作系统提供的一个操作的动作,双击过后,操作系统就会把这部电影从硬盘拷贝到内存之中,然后CPU就会处理内存里的这部电影的数据,一些数据变成声音,一些变成图像。关于图像的数据会发送给显卡并通过显示器就能让我们看到了,而声音的数据则是通过声卡让我们可以听到。
在上方关于电影的运行过程中,提到了硬盘,内存,CPU。这些又是什么?
这些都属于存储器,存储器是计算机用来存放数据的东西,因此它非常滴重要。
在你仔细看过上方关于电影的运行过程时,你是否会疑惑,为啥CPU不能直接操作硬盘而是操作内存呢?
是因为CPU的运行速度真的贼快,硬盘的速度跟不上,其实内存也跟不上,但是在内存之间还有缓存和寄存器,缓存和寄存器它俩兄弟的速度就比较接近CPU运行的速度了。
从某种意义上来说,缓存和寄存器也属于内存。So 我们说CPU直接操作内存。
一般计算器的内存只有几GB,而硬盘却有好几百GB,有的更是达到了1~2TB。那我们为啥不把内存造的跟硬盘一样大呢?
主要有两个原因:
一.同容量,内存造价高。
二.内存中的数据是暂时的,断电就会丢失数据,完全没得必要造的那么大。
下面我们来用一张图来更直观地表述存储器的运行速度比较:
字节
什么是字节?
字节是存储数据的基本单位,也是硬件所能访问的最小单位。注意最小的单位为比特位(bit)
为了更好地进行运行,我们把内存分成了很多的“小房间”,“小房间”里装的都是二进制代码,无非就是0和1。
存储单位也有很多种,并且和字节都可以进行换算:
存储单位 | 名字 | 换算 |
---|---|---|
bit | 比特位 | |
Byte(B) | 字节 | 1B=8bit |
KB | 千字节 | 1KB=1024B |
MB | 兆字节 | 1MB=1024KB |
GB | 千兆字节 | 1GB=1024MB |
小常识:
假设你买了一个128GB的U盘,但是当你使用的时候会发现根本没有128GB,排除掉厂商自身的问题,因为厂商是以1000为计算单位的,而我们使用的计算机是以1024为计算单位的!
数据类型
基本数据类型如下表:
注意:C语言中没有字符串类型。
所以在C语言中 ” char i = “ABC” ” 是错误的。
因为内存是有限的,为了不浪费,我们把数据分成了很多的类型,也更丰富地表达了生活中用到的值。
那么这些数据类型到底占用了多少内存空间呢?我们编写一个如下程序
经过编译——链接——执行过后产生如下数据
这意味着short,int,long,float,double,char分别占用2,4,4,4,8,1字节!
尤其值得注意的是,long即长整型所占的字节其实是4~8有些计算机输出的时候可能就会输出8,我上面列出的那个表中长整型所占的空间应该是4 ~ 8个字节
变量与常量
上方介绍了一些基本的数据类型,那么这些数据是如何存在我们的计算机中的呢?
这里就不得不提到变量了,变量就是存放这些数据的一个容器。在定义变量时放的是啥数据类型,那我们在定义的时候就把这个变量定义成什么类型。所以这就是为啥我们在变量的前面加上数据类型的原因。
生活中的变量比如:身高,体重,血型等
这些值每个人都不同,可以变化。而有一些不能改变的值就称为常量。
上面我们讲过了C语言的基本数据类型,实际上这些它们都是常量,分别称为整型常量、浮点型常量、字符型常量。
变量该如何定义呢?
基本的格式为:数据类型 变量名 = 要赋给变量的值;
比如 : int i = 0;(意思为把左边的数字赋给前面的变量i)
前面还没有讲过 C语言中的 “=”,其实和我们数学中的等号含义是不一样的,C语言中的等号为 “==”
我们还可以连续的定义 ,如:int i,j,k;
还可连续定义并赋值,如:int i = 1,j = 2,k = 3;
在C语言中定义变量的前面不能有其他的非定义的语句 ,像下面这种虽然在编译的时候并没有报错,但是实际上却是写法的一种错误,因为 “ i= 0;”是赋值,并不是定义变量。
如果我们没有赋值呢
在 vs2019中它就会报错,说我们使用了没有初始化的局部变量i。
其实初始化就是我们在定义的时候进行的赋值就是初始化,不是定义的时候就是赋值。
变量没有被赋值,那么则是定义了一块存储空间,而这块没有被赋值的存储空间如果之前使用过,就会有一些垃圾数据。操作系统虽然在上次使用完以后对这块存储空间进行了回收,但是并没有清空这个内存空间所遗留下来的一些数据。如果没有初始化的话,那么就还保留着这些垃圾数据。在以前的编译器中,上方的代码也是可以运行的,输出的则是一个就很小的随机值(这个随机值,是因为硬件中的高低电压而形成的。)但是泡泡猪发现在VS2019中编译不了,就不给大家示范了
变量的命名规则
(1)变量名由字母、数字、下划线组成,开头必须为字母、下划线,或者$
(2)定义变量除了某些公认的变量名(如:循环使用的变量i,j,k,等)一定要取得有意义。
(3)变量名中不限制大小写,但是大写得变量和小写的变量是有区别的·=,如:sum和SUM是不一样的变量
(4)变量名不能是关键字。
变量的分类:
全局变量
局部变量
变量类型分为两种,全局变量和局部变量。
如上图所示,此时a就是全局变量,b为局部变量,用非常通俗滴话来说,就是在{}大括号里面的就是局部变量,而在外面的就是全局变量。
那么我们再来看看如下代码
此时局部变量的名字和全局变量的名字一样,那么打印的时候,我该打印2021还是2020
不妨我们按下ctrl+F5走一波
输出的是2020,这说明了啥?
那就是当我们碰到全局变量和局部变量同名时,局部优先
变量的作用域和生命周期
作用域指滴又是啥嘞???
指的是这个变量起作用的范围。变量的作用域和生命周期如下表
变量 | 作用域 | 生命周期 |
---|---|---|
局部变量 | 变量所在的局部范围 | 进入作用域生命周期开始;出作用域生命周期结束 |
全局变量 | 整个工程 | 整个程序的生命周期 |
常量
常量分为四种常量:
(1)字面常量
(2)const 修饰的常变量
(3)define定义的标识符常量
(4)枚举常量
字面常量:
指的就是字面上可以直接看出它是一个常量,比如数字3,3.14等等。
const修饰的常变量:
这句话听上去是不是觉得非常的奇怪,居然还会有这种东西。首先我们来解释一下常变量这个名词,常变量是具有了常属性,也就是具有了常数的性质的一个变量。只要我们在变量的前面用 const 这个关键字将它给修饰一下,这个变量就变成了常变量。
别看它的名字就觉得它是一个常量,其实它的本质还是一个变量。
我们来用数组这个东西来验证一下,到这里的时候,泡泡猪还并没有给大家讲到数组的概念,我们只是在这里运用一下它的性质来验证“const可以将变量修饰成具有常属性的变量”。运用数组的那条性质为“定义数组时[]里面只能放常量或常量表达式”。
说了这么多,还是直接给本猪上代码吧
代码一
代码二
上方两个代码在编译的时候都会出现如下的报错,不信的同志们可以自己去敲一敲
这个报错说明即使变量a被const修饰成了具有常属性的常变量,但是它依旧还是一个变量。无情~对吧,就像是一个内心邪恶的人,不论在怎么修饰他,他的本质还是一个坏人。
#define定义的标识符常量
这个等之后我会来讲解
—枚举常量—
枚举的方式其实就是将所有可能的情况一一列举出来
上图关于性别枚举,有male,female,secret三者情况
我们在这里只给出了名字,并没有给出一一对应的值,是因为在枚举中,枚举值默认从0开始,往后一次递增1ss;对于上方的代码,就意味着male对应的值为0,female对应1,secret对应2
关键字
常见的关键字有
short | int | long | double | float | char |
---|---|---|---|---|---|
auto | break | case | const | continue | default |
do | else | enum | extern | for | goto |
if | register | return | signed | sizeof | static |
struct | switch | typedef | union | unsigned | void |
volatile | while | … |
这些关键字的作用,泡泡猪在后期的博客中会出一期精解说。
操作符
认识有哪些操作符为主,后期博客出精解说
算术操作符
+ - * \ %
加、减、乘 、除、取余
移位操作符
>> <<
右移 、 左移
位操作符
& ^ |
按位与、按位或与、按位或
赋值操作符
=、 +=、 -=、 *=、 /=、 &=、 ^= 、|=、 >>=、<<=
单目操作符。只有一个操作对象,可推出双目操作符和三目操作符
逻辑操作符
&& 逻辑与
|| 逻辑或
逗号表达式
exp1,exp2,exp3,…expN
从左向右依次计算,整个逗号表达式的结果,是最后一个表达式的结果
条件操作符
exp1?exp2:exp3
如果exp1成立,则选择exp2输出;
如果exp1不成立,则输出exp3.
字符串+转义字符+注释
字符串
像这种由双引号引起来的就叫做字符串字面值,简称为字符串
而字符串的结束标志为\0的转义字符,计算字符串的长度的时候\0是结束标志,不算作字符串的内容。
数组ch1中f的后面还隐藏着一个\0,而数组ch2中并没有\0这个转义字符,我们来看一下运行下来的结果
数组ch1中打印的就是abcdef,而数组ch2中打印出来的则是abcdef然后后面是一串随机值,因为在打印完数组中的元素后,计算机没有碰到\0,就会往后面一直打印,直到碰到\0才结束。所以后面才会是一串随机值。
在写一个代码来看看两个数组的空间长度
运行结果如下:
显示的是6和22,数组ch1中的元素个数是6,而数组ch2中的则是一个随机值,原因就是因为这个\0。特别值得注意的是隐藏的\0并不算作字符串的内容。
转义字符
假设你要在屏幕上打印一个目录:c:\code\test.c
我们要如何写代码呢?
但是实际运行下来的结果却是下面这样的
这里就不得不提到转义字符了
下面泡泡猪来带大家看一些转义字符
转义字符 | 释义 |
---|---|
\0 | 字符串的结束标志 |
\? | 在连续使用多个问号时,防止它们被解析成三字母词 |
\’ | 用于表示字符常量 |
\" | 用于表示一个字符串内部的引号 |
\\ | 用于表示一个反斜杠,防止它被解析成一个转义序列符 |
\a | 警告字符,蜂鸣 |
\b | 退格符 |
\f | 进纸符 |
\n | 换行 |
\r | 回车 |
\t | 水平制表符 |
\v | 垂直制表符 |
\ddd | ddd表示1~3个八进制数。比如:\123 |
\xdd | dd表示2个十六进制数字。如:\x31 |
从表格\a前面的转义字符,都可以理解为这个\使得\后面的字符失去了原本的含义
,单纯的把它变为了一个符号的字面形象。
让我们在屏幕中打印
一个单引号’
一个双引号"
一个\
编译——链接——执行之后:
我们已经大致看懂了转义字符,现在来看这样一道题:
这段程序输出的是什么?
是18?17?15?
是14!
这里尤其要注意的是238并不是一个8进制数,因为8进制数讲究的是满8往前进1,所以\23才算一个字符
注释
关于注释
它的作用大部分在于对比较难懂的代码进行解释,毕竟我们写代码的最终目的还是为了用户,用户也不是程序员。
也方便了我们回头来看自己写的代码的时候,能够轻松的看懂。
有两种注释的风格
C语言的注释风格:/* xxx */
-----缺点:不能嵌套注释
C++的注释风格://xxx
-----可以注释一行,也可以注释多行
流程控制
流程控制是啥意思呢?指指程序执行的顺序
流程控制的分类
(1)顺序执行
(2)选择执行
(3)循环执行
流程控制是由一个叫做图灵的人提出的,他认为不管什么样的程序,都可以用三种结构完成。这三种结构为顺序、选择和循环。
顺序执行,即按顺序一步一步执行
选择执行,即有选择性的执行
-----选择执行有两种语句:
(1)if 语句(2) switch语句
if(如果);switch(开关)
循环执行,即重复的执行
------循环执行有三种语句:
(1)for语句;(2)while语句; (3)do…while语句
凡是while和do…while循环能做的事,for循环都可以做。
函数
C语言的设计是模块化的设计,自顶而下的结构,结构化编程。
一个庞大的程序不可能是一个程序员做出来的,是由非常多的程序员共同完成。可能就会划分这些程序员负责哪些功能的实现,那些程序员负责哪些功能的实现。因为一些功能可以单独实现,因此这样就可以高效地写出这个程序。这个就是模块化的设计
那么C语言是如何实现模块化的设计的呢?
是用函数来实现它的模块化设计的。
数组
数组是一组相同元素的集合
指针
C语言的灵魂就是指针,指针非常重要,但是也非常的难。
在前面的章节里,泡泡猪有说过,为了有效和方便的使用内存,我们把内存分成了很多小小的内存单元格,这些内存单元格就像是一个个小房间一样。我们划分的每个内存单元的大小都是一个字节(Byte)。
讲到了这里,我们在回头看一下这个语句的含义:
向内存申请了4个字节(因为定义成整型,整型占四个字节),里面存放10
这么多的内存单元,而我要找到的内容该怎么方便的寻找呢?我们给这些“小房间”进行了编号,以后就可以根据“房间号”来访问了,C语言中,这些编号被称为内存单元的地址。
形象的来说:
内存单元的地址就好比房间号
内存单元的内容就好比房间里的客人
程序中,一般是通过变量名对内存单元进行存取操作,对变量值的存取是通过地址进行的。这种方式为直接访问方式。有直接访问方式,也就是说还有间接访问模式,这种模式是什么样的呢?就是把一个变量的地址放到另外一个变量中。意味着另一个变量里现在放的不是数据,而是那一个变量的地址。这个变量是一个特殊的变量,它的作用是存放地址的。
刚才我们形象的把内存单元的地址比作了房间号,而这个房间号就指向了那个房间的位置,也就是说,地址“指向”该变量单元。C语言中我们把地址称为“指针”,通过地址我们可以找到以它为地址的内存单元。即我们通过指针可以找到以它为地址的内存单元。
从上面的讲述中,可以看出,指针就是地址,地址就是内存单元的编号。这里不在过多叙述。要注意区分指针和指针变量
指针就是地址,指针变量是存放地址的变量。
下面我们来定义一个指针变量:
我们之前讲过基本数据类型,并且得出了每个数据类型所占空间的大小,我们现在也照样来算一下这种特殊变量所占内存空间的大小,接下来该用到我们熟悉的sizeof()了
我们运行下来可能会让你大吃一惊,为啥嘞?因为你会发现这些特殊的变量所占的内存空间大小都是4个字节
要注意的是。指针变量的大小在32位平台上是都是4个字节,而在用64位的平台上是8个字节
结构体
结构体是使得C语言更有能力去描述复杂的类型、之后结构体更会影响到我们以后对数据结构和面对对象编程的学习。比如说,描述一本书,一本书的描述就包括:书名+作者+书号+售价这几项信息。这几项信息都有一个内在的联系,它们是一个整体,都表示同一本书的信息,如果把它们单独定义变量的话,就无法体现出它们的内在联系。这里就可以使用结构体来描述。结构体是将不同类型的数据按照一定的功能需求进行整体封装。
例如:
以上仅为大致,每一个知识点泡泡猪会重新仔细的分段讲解
如有问题,请联系,谢谢!