室友只用了一把王者的时间就入门了「C 语言」
🌟 前言
大家好,我是 Edison😎
其实最近在备考、刷题过程中,发现 C 语言中的某些知识点竟然遗忘了;
从而导致又跑去翻书、翻笔记等,很浪费时间,于是乎,就打算把「C 语言」整个系列从头到尾全部梳理一遍;
一方面,方便自己查阅,省去了看笔记、看书的时间; 另一方面,也给各位老铁提供了一篇查阅的资料,欢迎前来指正;
Let’s get it!
本章目标
基本了解 C 语言的基础知识,对 C 语言有一个大概的认识。
每个知识点就是简单介绍,不做详细讲解; 后续会慢慢的把每个章节全部拿出来重点说明;
本章重点
一、什么是 C 语言?
C 语言是一门通用计算机编程语言,广泛应用于底层开发。
C 语言是一门面向过程的计算机编程语言,与 C++,Java 等面向对象的编程语言有所不同。
C 语言的设计目标是提供一种能以简易的方式编译、处理低级存储器、产生少量的机器码以及不需要任何运行环境支持便能运行的编程语言。
🍑 计算机编程语言
计算机语言顾名思义就是 人和计算机交流的语言;
即人给计算机发送指令,计算机读懂以后按照指令执行我们想要计算机执行的工作。
常用的计算机语言有:C、C++、JAVA 等等。
🍑 底层软件开发
我们现在使用的电脑,俗称为:硬件;
但是要让电脑工作就必须要给电脑装一个操作系统,比如:Windows、Linux 等;来进行对硬件的操作。
操作系统和硬件由 驱动层 相关联。因此,硬件、驱动和操作系统就叫做底层,所以我们写一个操作系统、驱动软件等这些操作就叫做底层开发。
在底层往上就是应用层,即我们能直观感受到的东西,比如应用软件:QQ、微信。
C 语言也可以用于应用软件开发,但是相比其他语言就显得很劣势。
🍑 语言的发展过程
最初的编程语言我们称为 机器语言,即 二进制的语言,要想实现某一个功能就要写好多二进制的序列。
由于太难理解后来出现了 汇编语言,汇编语言用助记符代替机器指令的操作码,我们用助记符就可以更加容易写代码。
后来发展出了更加容易的 B 语言和 C 语言,更加贴近我们人的逻辑。
但后来由于 C 语言的标准不统一,这就导致 A 公司的代码在 B 公司上就无法运行,因此制定了 ANSI C,即 C 语言国际标准。这些标准约束了 C 语言的语法规则。
🍑 ASCII 码表
由于计算机中只有二进制数字,一些符号没法表示;
例如,像 a、b、c、d 这样的 52 个字母(包括大写)以及一些常用的符号(例如*、#、@等),因此约定一套编码来表示这些符号,这就是 ASCII 码表。
🍑 编译器
编译器主要有 Clang、GCC、WIN-TC、SUBLIME、MSVC、Turbo C 等。
编译器就是编译代码的工具,用来将我们写的 C 代码转换成电脑能读懂的二进制;
需要注意的是:我们常用的 VS2019、Dev C++、VSCode 等;这些严格来讲并不能称为编译器,它们是由编译器组成的集成式开发环境。
二、第一个 C 语言程序
我用的编译器是:VS2019
🍑 主函数
主函数是 C 语言的程序入口,程序开始执行的位置。
一个源文件当中只能有一个主函数,要不然编译器就不知道从哪个入口开始执行了。
📝主函数代码示例
运行结果
代码解释
int
是函数返回值的类型,最常用的是整型;
main
是主函数的函数名;
()
是函数的参数,由于主函数一般情况下为无参,因此()
里面的内容可以为空;
{}
里面是主函数的内容;
return 0;
表示函数的返回值;
printf
是 C 语言提供的库函数,它的具体用法是printf(“要输出的内容”)
;
#include <stdio.h>
是printf
库函数的头文件;
stido
翻译为标准输入输出;
我们的输入和输出函数都在这个头文件里面,每次要使用这些函数都要引用这个头文件。
三、数据类型
我们在对一件事物的描述需要各种各样的数据;
比如价格、体重、身高等描述就要用到整数、小数等数据类型。
因此 C 语言中引入了这些类型
🍑 存储单位
在计算不同数据类型大小之前首先要清楚计算机中的单位;
计算机中最小的单位为 bit(比特),即 存放一个 1 或者 0 的空间。
计算机是一个硬件,通电后,可以识别电信号,0 和 1 代表两种逻辑状态,1 代表电路连通状态,0 代表电路断开状态;
存放一个 0 或者 1 的空间大小为 1 个比特位。
详见的存储单位如下👇:
计算机在存储数据和执行指令的时候是以 8 个比特(bit)为单位的,也就是 1 个字节(byte);
🍑 类型大小
我们可以用
sizeof
操作符来计算不同数据类型在内存中所占空间的大小,单位是字节(byte);可以看出,不同的数据类型所占空间大小是不同的;
我们可以使用不同整形和浮点型,防止空间浪费;
比如
short
短整型的二进制换算成十进制,可以表示的范围是-32768~32767
;
int
整型范围是-2147483648 ~2147483647
,因此在描述年龄等较小的数据时,选择short
短整型可以很好地节约空间。
单精度浮点数占 4 个字节,双精度浮点数占 8 个字节。
单精度浮点数有效数字 8 位,双精度浮点数有效数字 16 位。
在使用浮点型时也可以使用不同的类型来节约内存。
🍑 数据类型的输出格式
不同的数据类型有不同的输出格式
不同的类型可以用多种格式打印
%x
是 16 进制输出,因此在打印输出时,会将a
转换为 16 进制再进行输出。
四、变量和常量
常量,顾名思义就是不能改变的量,在生活中常量有很多,比如圆周率、身份号码等。
变量,就是值可以被改变的量,比如体重、年龄、薪资等。
🍑 定义变量的方法
在 C 语言中,我们一般用
数据类型 + 变量名 + 赋值操作符(=) +变量的值
这种形式来定义一个变量。
比如我们要定义一个整形变量 age,它的值为 10,👇
同理要定义一个浮点型变量 weight 和 字符型变量 ch,也是一样👇
注意🎃
在 C 语言中,
=
并不是我们数学中的等号,而是一个赋值操作符;
int age = 10
意为:定义一个整形变量 age,将 10 赋值给 age,此时 age 的值就是 10;
这个过程我们称为给 age 赋初值,如果不给 age 赋初值,age 将无法使用,因为编译器也不知道 age 的值是多少。
还可以这样做👇
🍑 变量的分类
变量分为:局部变量和全局变量
全局变量:定义在代码块
{}
之外的变量;
局部变量:定义在代码块
{}
之内的变量;
总结✨
全局变量与局部变量名相同,局部变量优先。
但是在写代码过程中不建议相同,因为会造成不必要的错误
比如👇
上面的局部变量
global
变量的定义其实没有什么问题的!
结果应该为局部变量的值,也就是
global = 2020
;
🍑 变量的作用域
作用域(scope),程序设计概念,通常来说,一段程序代码中所用到的名字并不总是有效或者可用的;
而限定这个名字的可用性的代码范围就是这个名字的作用域;
1、局部变量的作用域是变量所在的局部范围。
2、全局变量的作用域是整个工程。
举个栗子🌰
分析👇
a 是局部变量,a 的定义范围是:a 所在的那个
{}
;它的作用域就是:它所在的{}
,出了{}
以后 a 就不能使用了;
b 是全局变量,作用域是整个工程,因此 b 的作用域并不受
{}
的限制。
c 是局部变量,c 的作用域是整个
main
函数所在的范围,由于printf(“c=%d”, c);
所在的{}
也属于main
函数所在的范围,因此可以打印输出。
🍑 变量的生命周期
变量的生命周期指的是变量的创建到变量的销毁之间的一个时间段;
1、局部变量的生命周期是:进入作用域生命周期开始,出作用域生命周期结束。
2、全局变量的生命周期是:整个程序的生命周期。
🍑 常量
C 语言中的常量和变量的定义的形式有所差异。
C 语言中的常量分为以下以下几种:
🍅字面常量
也就是程序中出现的数字,字符等;
代码示例👇
10 和 w 就是字面常量。
🍅 const
修饰的常变量
const
修饰的常变量无法修改a 不是常量,只是具有常属性,不能被修改而已
🍅 #define
定义的标识符常量
define
定义的常量不能被修改
这种定义方式相当于给字面常量起别名,它的别名具有字面常量的属性,在使用时别名直接替换为字面常量;
代码示例👇
🎃但是有一点需要注意
🍅 枚举常量
通过枚举关键字 enum 定义的常量;
这里了解一下就可以了,在此不作过多介绍
五、字符串+转义字符+注释
🍑 字符串
由双引号引起来的一串字符称为字符串字面值,或者简称字符串。
注:字符串相当于多个字符连续存放在字符数组中,但是字符串的结尾是一个隐藏的
\0
转义字符。
在计算字符串长度的时候
\0
是结束标志,不算作字符串内容。
\0
对于字符串非常重要,在打印字符串时,\0
可以使打印停止。
比如下面的代码👇
打印结果
为什么会这样呢?在监视中可以看到字符数组的内容:
从监视中看出 arr1 在结尾处比 arr2 多了一个
\0
,而 arr1 和 arr3 是一样的;
arr1 字符串后面有一个隐藏的
\0
,因此在打印输出时,遇到\0
后,打印停止;
arr2 字符串后面没有
\0
,因此在打印完 abc 以后还会继续打印,直到遇到\0
才会停止;
arr3 字符串有
\0
,遇到\0
后,打印停止。
由于字符串中有一个隐藏的
\0
,因此字符数组的大小比我们输入的字符,多 1 个;
当字符数组的大小比我们存入数组的字符串大时,多出的空间会全部补为\0
🍑 转义字符
假如我们要在屏幕上打印一个目录: c:\code\test.c
我们该如何写代码?
实际上程序运行的结果是这样的👇
这里就不得不提一下转义字符了。
转义字符顾名思义就是转变意思。
下面看一些转义字符
假设我们要在屏幕上打印一个单引号'
,怎么做?
假设要在屏幕上打印一个字符串,字符串的内容是一个双引号"
,怎么做?
学会了吗?我们来看一道某大厂的笔试题吧
strlen 这个函数可以求字符串的长度;在这里
\t
和\32
都是一个字符;
\t
是水平制表符算作一个字符可以理解,\32
表示一个八进制的数字;
你可能会问:为什么不是
\328
呢?那是因为 8 进制当中没有 8;
编译器先将 32 转化成十进制也就是 40,再从 ASCII 码表中找到 40 代表的字符,
\32
就相当于那个字符。注意:单个的
\
是转义字符,编译器发现没有\c
等的转义对应的字符所以忽略这个\
🍅补齐字符
这个补齐字符很简单,我们直接看代码👇
运行结果
🍑 注释
1、代码中有不需要的代码可以直接删除,也可以注释掉
2、代码中有些代码比较难懂,可以加一下注释文字
举个栗子🌰
注释有两种风格: 1、C 语言风格的注释
/*这是一个注释*/
;缺陷:不能嵌套注释
2、C++风格的注释
//这是一个注释
;它可以注释一行也可以注释多行,推荐使用这种;
六、选择语句
顾名思义,就是根据不同的条件选择性地执行不同的语句。
如果你好好学习,校招时拿一个好 offer,走上人生巅峰。
如果你不学习,毕业等于失业,回家卖红薯。
这就是选择!
代码示例
如果 if 里面的条件成立,就会执行 if 语句里面的代码;
如果不成立,则执行 else 里面的代码。
七、循环语句
有些事必须一直做,比如我日复一日的学习,比如大家,日复一日的打游戏🤣。
还比如:
C 语言中实现循环的方式:
1、while 语句
2、for 语句
3、do … while 语句
由于只是初识 C 语言,因此在这里只挑 while 循环来说明:
以上代码可以自己运行一下😏
八、函数
当一段代码(比如两个数相加,相减)需要不断执行的时候,我们就可以将这段代码写成一个函数;
在需要执行这段代码的时候,只需调用函数就可以,以此来简化代码。
比如一个加法的函数👇
通常情况下我们是这样写的
但是可以用函数来实现
函数的特点就是简化代码,代码复用。
九、数组
要存储 1-10 的数字,怎么存储?
C 语言中给了数组的定义:一组相同类型元素的集合
🍑 数组的定义
int 是数组的类型;
arr 是数组的名字;
[10]
是数组的大小,数组的大小也可以不写,编译器会自动识别数组的大小;
{ }
内是数组的每个元素。
🍑 数组的使用
C 语言规定数组的每个元素都有一个下标,下标是从 0 开始的。
数组可以通过下标来访问的。 比如:
🍑 数组的使用
强调一点:要访问数组的元素,就要用到数组的下标,
比如
arr[i]
中,i 就是数组的下标。
数组下标是从 0 开始的整数,因此数组的第一个元素的下标为 0 而不是 1。
以此类推,第二个元素的下标为 1,第三个元素下标为 2 …
十、操作符
顾名思义就是对变量进行操作的符号,比如加减乘除等,在此仅做简单的介绍。
🍑 算术操作符
+
:加
-
:减
*
:乘
/
:除
%
:取模(即求一个数除以另一个所得到的余数))
🍑 移位操作符
<<
:左移
>>
:右移
位移操作符移动的是变量的二进制位而不是十进制位
左移操作符:
<<
将二进制位的位数向左移动,移动以后移出位丢弃,右边补 0,比如将数字 1 进行左移一位。
代码示例
移位演示
打印结果
🍑 位操作符
&
:与运算
|
:或运算
^
:异或运算
那怎么计算的呢?
它们都是对二进制位进行运算;
&
:只要有 0 就是 0,相同为 1 才是 1;
|
:只要有 1 就是 1,相同为 0 才是 0;
^
: 两个位相同为 0,相异为 1;
比如将 5 和 3 进行与运算:
演示:
🍑 赋值操作符
=
+=
-=
*=
/=
&=
^=
|=
>>=
<<=
怎么理解呢?
=
:将右边的值赋值给左边;
+=
:对原本的操作进行了简化;
比如:
a += 1
等价于a = a+1
只是a += 1
更简便一些, 其他操作符也是同理;
🍑 单目操作符
这里单独说一下前置++和后置++
++
在前,先自加 1,再使用;👇
a 先自加 1,再将自己的值赋值给 b
++
在后,先使用,再自加 1;👇
a 先将自己的值赋值给 b,再自加 1
同理,前置
--
和后置--
也是一样;
🍑 关系操作符
>
:大于
>=
:大于等于
<
:小于
<=
:小于等于
!=
:不相等
==
:相等
🍑 逻辑操作符
&&
:逻辑与,可以理解为 并且;
||
:逻辑或,可以理解为 或者;
🍑 条件操作符
也叫做三目操作符;
exp1 ? exp2 : exp3
代码示例
如下是一段普通的判断代码👇
但是此代码可以用条件操作符来表示
是不是简洁很多了?
🍑 逗号表达式
exp1, exp2, exp3, …expN
整个表达式的结果是:最后一个表达式计算结束的结果
代码示例:
分析:
先计算
a+1
的值然后将其赋值给 b,此时 b 的值为 2,a 的值为 1;
再计算
b+1
的值然后将其赋值给 a,此时 a 的值为 3,b 的值为 2;
最后计算
a+b
的值并将结果赋值给 b,此时 b 的值为 5;
整体表达式的结果就是最后一个表达式的结果,最后一个表达式的结果为 5;
因此整体表达式结果为 5;
🍑 下标引用、函数调用和结构成员
[]
()
.
->
结构体会讲到,此处不过多讲解
十一、常见关键字
C 语言内置的关键字。只需初步了解即可。
另外记住,变量名不能和关键字相同,要不然编译器无法区分关键字和变量名。
🍑 关键字 typedef
typedef
顾名思义是类型定义,这里应该理解为类型重命名。
🍑 关键字 static
在 C 语言中:
static
是用来修饰变量和函数的;
1、修饰局部变量-静态局部变量;
2、修饰全局变量-静态全局变量;
3、修饰函数-静态函数;
🍅修饰局部变量
代码示例👇
test
函数中的局部变量 i 在test
函数运行结束后并没有被销毁,每次调用test
函数都会使 i 自增;
另外在第一次调用
test
函数的时候 i 已经被赋予初值 0 了,出了函数并不会被销毁,此后继续调用函数static int i=0
这条语句都不会被执行;
也就是说 i 并不会被再次赋值为 0。
为了更清晰地对比,我们可以观察把 static 去掉以后程序的运行结果
static
修饰局部变量改变了变量的生命周期,让静态局部变量出了作用域依然存在,到程序结束, 生命周期才结束。
🍅修饰全局变量
一个全局变量被 static 修饰,使得这个全局变量只能在本源文件内使用,不能在其他源文件内使用。
🍅修饰函数
一个函数被 static 修饰,使得这个函数只能在本源文件内使用,不能在其他源文件内使用。
效果与 static 修饰全局变量类似
十二、#define 定义常量和宏
#defne 宏名(被替换的内容)(要替换的内容)
代码示例:
运行结果:
十三、指针
要理解指针,首先要理解内存
🍑 内存
内存是电脑上特别重要的存储器,计算机中程序的运行都是在内存中进行的。
所以为了有效的使用内存,就把内存划分成一个个小的内存单元,每个内存单元的大小是 1 个字节(byte)。
为了能够有效的访问到内存的每个单元,就给内存单元进行了编号,这些编号被称为该内存单元的地址。
变量都有地址,取出变量地址如下:
&
操作符可以将 num 的地址取出,然后赋值给指针 p。
但我们知道 num 占 4 个字节,因此它有 4 个地址,
&
取出的是 num 的起始位置地址。
运行结果
00F3FC5C
是第一个起始位置的地址;
那地址如何存储?需要定义指针变量。
指针的使用实例:
解释说明:
*
是解引用操作符,*p
是通过 p 找到 p 指向的对象,即 num;
p 也是一个指针变量,它也有地址。
以整形指针举例,可以推广到其他类型,如:
总结如下:
我们取出一个变量的地址的时候,这个地址便称为 指针;
而这个地址如果要存起来的话,需要存到一个变量里面去,这个变量就被称为 指针变量;
指针变量可以对它进行 解引用 操作;
指针是一个变量,用来存放地址;
🍑 指针变量的大小
那么指针有没有大小呢?
答案肯定是有的,但是不同的平台,指针大小是不一样的;
比如,以 32 位平台为例,指针的大小就为 4 个字节👇
但是以 64 位平台为例,指针的大小就为 8 个字节👇
结论:指针大小在 32 位平台是 4 个字节,64 位平台是 8 个字节。
十四、结构体
结构体是 C 语言中特别重要的知识点,结构体使得 C 语言有能力描述复杂类型。
比如描述学生,学生包含:
名字+年龄+性别+学号
这几项信息。
这里只能使用结构体来描述了。
例如:
结构体的初始化:
我们通过结构体创建一个学生 s,并对其进行初始化操作;
此时我们可以通过
.
(点操作符) 来访问结构体具体的成员;
具体语法为:
结构体变量名.结构体具体内容
,比如:s.name
;
我们也可以创建结构体指针来指向 s,并通过
->
(箭头操作符) 来通过结构体指针来访问结构体成员;
具体语法为:
结构体指针->结构体内容
,比如:ps->name
;
总结
🤗作者水平有限,如有总结不对的地方,欢迎留言或者私信! 💕如果你觉得这篇文章还不错的话,那么点赞👍、评论💬、收藏🤞就是对我最大的支持! 🌟你知道的越多,你不知道越多,我们下期见!
版权声明: 本文为 InfoQ 作者【Albert Edison】的原创文章。
原文链接:【http://xie.infoq.cn/article/2e1310fcc0f68f8cf899d35d5】。文章转载请联系作者。
评论