作者将在网上学习的C语言的知识记录并以文章形式发表。本文主要还是学习笔记的类型,按顺序简单介绍C语言知识点,内容较为浅显。本人目前还是一个新手,难免存在理解错误或不透彻的地方,在此先感谢各位读者朋友指正!
什么是C语言?
C语言是一门通用计算机编程语言,是许多其它编程语言的基础,可以用来开发应用软件、驱动、操作系统等。
第一个C语言程序
1.打开VS(这里作者使用的是Visual Studio 2022)
2.创建新项目——空项目——修改项目名称、位置
3.创建源文件(.c 源文件 .h 头文件)——源文件右击——添加——新建项——C++文件、名称注意后缀.c
.cpp后缀编译器会按照c++语法编译代码 .c后缀编译器会按照c语言来编译
4.写代码
(// + 绿色字体是注释)
请试着打出如下代码:
在菜单栏中找到本地Windows调试器,
或使用快捷键ctrl+f5运行代码,结果如下。
数据类型
char 字符数据类型
short 短整型
int 整型
long 长整型
long long 更长的整型
float 单精度浮点数
double 双精度浮点数
不同数据类型在内存中所占大小是不一样的,应在适当的时候选用合适的类型,通过类型向内存申请空间。
求每种类型的大小?(单位:字节)
计算机中的单位:
bit - 比特位
byte - 字节 = 8 bit
KB -千字节 = 1024 byte
MB -兆字节 = 1024 KB
GB -吉字节 = 1024 MB
TB -太字节 = 1024 GB
PB -拍字节 = 1024 TB
变量、常量
生活中的有些值是不变的(比如:性别,圆周率,身份证号码,血型等),有些值是可变的(比如:年龄,体重,薪资等)
c语言中,不变的就就用常量的概念表示,变化的就用变量表示。
1.定义变量
short age = 20;
int high = 180;
float weight = 88.5;
即变量类型 (空格)变量名 = (赋值);
2.变量的命名
- 只能由字母(包括大小写)、数字和下划线组成。
- 不能以数字开头。
- 变量名中区分大小写。
- 长度不超过63个字符。
- 变量名不能使用关键词。
3.局部变量和全局变量
顾名思义,全局变量就是整个工程都能用的,而局部变量只能在{ }内部使用。
同一范围内不能重复定义,冲突时优先使用局部。但不建议使用重复名称。
4.变量的使用
这里可能报错,注意错误信息提示,将#define _CRT_SECURE_NO_WARNINGS复制到源文件第一行。想永久改变,需要改new++file.cpp文件。22版文件目录如下:
复制一份到桌面,以记事本打开文件,输入代码,保存,替换原来的文件。
5.变量的作用域和生命周期
-
作用域(scope),通常来说,一段程序代码中所用到的变量并不总是有效/可用的,而限定这个变量的可用性的代码范围就是这个变量的作用域。
-
局部变量的作用域就是变量所在的局部范围。全局变量的作用域就是整个工程。
-
生命周期指的是变量的创建到变量的销毁之间的一个时间段。
-
局部变量的生命周期是:进入作用域生命周期开始,出作用域生命周期结束。全局变量的生命周期是:整个程序的生命周期。
6.常量
c语言中的常量有以下几种:
- 字面常量
- const修饰的常变量
- #define定义的标识符常量
- 枚举常量
举例:
字符串
字符串:双引号引起来的一串字符
字符串的结束标志是一个\0的转义字符。\0是结束标志,不算作字符串内容,不计入长度。
按f10进入调试,点击菜单栏调试——窗口——监视,打开监视窗口,在名称列下添加要监视的项,这里我们分别添加arr1和arr2,继续按f10执行语句。
可以看到arr1中有7个元素,arr2中有6个元素,arr1中多了一个\0。
那么打印字符串时为什么arr2后会有“烫烫烫……”呢?(一定是代码想吃麻辣烫了)
其实是因为arr2没有结束标志,打印时会持续往后面的内存中找,直到找到结束标志\0。
C语言程序在尝试访问未经初始化的内存时,该区域的数据是不确定的。内存中的随机值被解释为了中文字符编码,而“烫”字在某些编码表中的编码恰好可能是非常常见的无效或垃圾值。
这时我们在arr2中加入\0,即可打印正常。
我们再来求一下字符串长度,看看转义字符是否计入字符串长度。
可知,转义字符不计入长度。
转义字符
转义即转变含义,下面都是转义字符
\? 在书写连续多个问号时使用,防止他们被解析成三字母词。
\' 用于表示字符常量'
\" 用于表示一个字符串内部的双引号
\\ 用于表示一个反斜杠,防止它被解释为一个转义序列符。
\a 警告字符,蜂鸣
\b 退格符
\f 进纸符
\n 换行
\r 回车
\t 水平制表符
\v 垂直制表符
\ddd d d d表示1~3个八进制的数字。如:\130 表示字符X
\xdd d d表示2个十六进制数字。如:\x30 表示字符0
注:八进制130变十进制为88,对应ASCII码为X。130变十进制需要1*8^2+3*8^1+0*8^0=88
上面的转义字符大家可以自己打出来试试
求下面代码中字符串的长度
结果如下:
注释
注释:用来解释说明,前文代码中绿色部分都是注释。
/*xxxxxx*/ 或 //xxxxxx (快捷键ctrl+k,ctrl+c)
注:/*xxxx*/不支持嵌套使用,即/*xxx/*xxxx*/xxx*/
选择语句
if(表达式)
{语句1}
else
{语句2}
如下:
运行代码:
输入1,敲回车:
大家可以自己试试输入0的结果。
循环语句
while(判别式1)
{结果1}
if(判别式2)
{结果2}
如下:
中途跳出循环则打印“继续加油”。
函数
这里函数并不是数学概念中的函数。
c语言中函数的目的就是简化代码,代码复用。
将上述代码写成函数如下:
这样先写出函数,就可以在后续直接代入使用,而不用每次都打一遍表达式。
数组
数组:一组相同类型元素的集合
如:int arr[10] = {10,11,12,13,14,15,16,17,18,19};//定义一个整型数组,最多放10个元素
从左到右依次叫做数组数据类型,数组名,数组元素个数,数组元素。 (数组元素个数空着不写时,编译器会根据元素个数自动确定,但建议养成标明个数的好习惯)
c语言规定,数组的每个元素都有一个下标,下标从0开始。10个元素时,下标范围即0~9。数组可以通过下标来访问,如想要访问下标为8的元素:
依次访问每一个元素:
操作符
1.算术操作符
+ - * / %
注:/ 除号两端都是整数时,执行整数除法,结果取整。两端只要有一个浮点数就执行浮点型。
% (取模)即取余数,如 7 % 2 = 1,即 7除以2余数为1。两端只能是整数。
2.移位操作符
>> <<
3.位操作符
& ^ |
4.赋值操作符
= += -= *= /= &= ^= |= >>= <<=
例:a += 3 即 a = a + 3,其余同理。
5.单目操作符
单目操作符(只有一个操作数):
! 逻辑反操作(真假变换)c语言中0表示假,非0表示真
- 负值
+ 正值
& 取地址
sizeof 操作数的类型长度(以字节为单位)
~ 对一个数的二进制按位取反
-- 前置、后置--(例:int a = 10; int b = a --; 即 int b = a; a = a - 1;后置--,先使用a,再 --)
++ 前置、后置++ (前置则是先 ++,再使用)
* 间接访问操作符(解引用操作符)
(类型) 强制类型转换 int a = (int)3.14; //3.14浮点数,默认为 double类型,使用(int)强制转换为整型,结果为3
6.关系操作符
> >= < <= != ==
(=为赋值,==为相等)
7.逻辑操作符
&& 逻辑与 || 逻辑或
8.条件操作符
exp1 ? exp2 : exp3(表达式1为真,则执行表达式2,不执行表达式3;反之,表达式1为假,则不执行表达式2,执行表达式3。)
9.逗号表达式
exp1,exp2,exp3, ...expN(从左到右依次计算,整个表达式的结果是最后一个表达式的结果)
注:从左往右依次计算,c = a - 2得c = 8,a = b + c得a = 28,c - 3得c = 5。
10.下标引用、函数调用和结构成员
[] () . ->(后两个是结构成员)
关键字
关键字是语言本身预先设定好的,用户自己不能创造关键字。
常见关键字:
下面介绍两个关键字
1.typedef
(类型定义,即为类型重命名)
如:
2.static
(用来修饰变量和函数)
修饰局部变量的称为静态局部变量;修饰全局变量的称为静态全局变量;修饰函数的称为静态函数
1)修饰局部变量
提问:下图代码运行结果为?
答:
(因为再此进入循环后a被重新赋值。)
在函数定义中加入static,代码及结果如下:
static修饰的局部变量出了作用域后不销毁。本质上,static修饰局部变量时改变了变量的存储位置。static影响了变量的生命周期,使其和程序的生命周期一致。
2)修饰全局变量
源文件下新建项add.c,输入int g_val = 2024;这是一个全局变量。
在源文件test.c中输入
int main()
{
printf("%d\n", g_val);
return 0;
}
此时test.c中g_val报错。
test.c中想使用add.c中的全局变量时,只需要声明一下外部符号,如下。
此时在add.c中的全局变量前加上static,运行代码会报错。
“无法解析的外部符号g_val”
全局变量具有外部连接属性。static修饰全局变量时,这个全局变量的外部连接属性就变成了内部连接属性,只能在本源文件内使用,不能在其它源文件使用。
3)修饰函数
与修饰全局变量同理。函数也具有外部连接属性。
static修饰函数后,test.c中运行代码报错。
#define定义宏
#define ADD(x,y) ((x)+(y))中ADD是宏名,(x,y)是宏的参数,参数是无类型,((x)+(y))是宏体。使用时其实是将ADD(a,b)中a替换x,b替换y。宏就是替换作用,与函数不同。
指针
1.内存
我们先来了解一下内存。
内存是计算机组成结构中重要的存储器,用于存放CPU中的运算数据和硬盘等外部存储设备交换的数据。计算机中所有程序的运行都在内存中进行。计算机将内存划分为了一个个小的内存单元,每个内存单元大小为1个字节,每个内存单元都有编号,这样便于管理和使用内存。
内存编号可以称为地址,在c语言中也可称为指针。
CPU在内存或硬盘里面寻找一个数据时,先通过地址线找到地址,然后再通过数据线将数据取出来。地址线就是用来传输地址信息用的。一根地址线只能表示1和0(高电压表示1,低电压表示0)。32位机器有32根地址线,那就有2^32个地址序列,每个地址序列对应一个内存单元,每个内存单元大小为1个字节,那么就可以管理2^32个字节的空间,换算一下即4GB。
当我们创建变量时,就是在向内存申请空间,所以变量也有地址。
int是整型,占4个字节。
这4个字节都有地址,那这个变量的地址应该是什么呢?答案是第一个字节的地址(较小的地址)。
我们按f10进入调试,打开菜单栏的调试——窗口——监视。在名称栏分别输入a和&a。
之后我们找到调试——窗口——内存。在地址栏输入&a,敲回车,会发现显示的地址与监视窗口中&a的值一样。接下来把列数改为4,即4个字节。
最左侧为地址,中间列为内存中的数据,最右侧为不准确的内存数据的文本解析。
我们知道10进制有0~9十个数字组成,16进制则是0~9 a b c d e f 这十六个数字组成(a=10)。
a占了4个字节,即32个比特位,写成二进制为0000 0000 0000 0000 0000 0000 0000 1010,写成十六进制为00 00 00 0a(这里建议搞不明白进制转换的同学网上找找有关的教学视频)。
而内存地址通常以十六进制表示,存入内存时又是倒着存,所以我们就会看到a的内存数据为0a 00 00 00
我们回到这张图:
变量a的地址是第一个字节的地址,即......FFBE4,那第二个字节的地址就是......FFBE5,第三个字节的是......E6,第四个字节的是......E7,转到第二行第一个,它的地址正好是......E8。
存放指针或地址的变量就被称为指针变量。
*是来说明p是指针变量
int说明p指向的对象是int类型
那我们把地址存起来有什么用呢?
这样便把a重新赋值为了20。
如此我们就可以通过指针来访问或修改一个地址对应的内存数据了。
2.指针变量的大小
我们可以思考一下不同类型的指针变量的大小应该是多少?
会发现不同类型的指针变量的大小是一样的。指针变量存放地址,所以指针变量的大小取决于一个地址存放时需要多大的空间:32位平机器上地址是32个bit位,即4个字节;64位机器上地址是64个bit位,即8个字节。
结构体
对于复杂对象,我们难以用简单的类型(char、int、long......)来描述,如书本包括书名+作者+出版社等信息,这时就只能用自定义类型来描述了,这其中一种便叫做结构体,关键字为struct。
也可以通过传地址来做:
printf("%s %d %s %s\n", (*ps).name, (*ps).age, (*ps).sex, (*ps).tele);
也可以简化为:
printf("%s %d %s %s\n", ps- >name, ps- >age, ps- >sex, ps- >tele);
上面的两种方式:
结构体对象.成员名
结构体指针变量- >成员名
即前文操作符里提到过的结构成员
好啦!至此《C语言零基础学习》算是结束啦!也感谢能看到这里的朋友们!但愿我写的还能让人看懂……遇到不明白的还是要网上多多学习啊!希望我们都可以不断成长!