目录
前言
在参加这次培训之前,对C语言只有很浅的了解,来到了华清远见后对C语言才有了系统的了解和学习。 以下我将介绍我培训的内容!
day1
首先要了解C语言基础的东西,如数据类型,控制语句,存储类型等等。
数据类型包含char、short、int、long、float、double等等
包含auto、static、extern、register
day2
存储类型
auto修饰局部变量,修饰的变量存储在栈区
static修饰局部变量和全局变量,修饰的变量存储在静态区。
static修饰局部变量,1、延长生命周期。2、未初始化,其值为0。3、初始化了,只能初始化一次
extern修饰全局变量,修饰的变量存储在静态区。
extern告诉编译器,该变量已经在其他文件中定义
register修饰局部变量,修饰的变量存储在寄存器。寄存器是cpu内部的存储器,内存小,但读写速度快,因此寄存器满的时候,存储在栈区
day3
数据类型转换
强制类型转换和隐式类型转换
强制类型转换:(要强制转换的类型)变量名
隐式类型转换(编译器自己转换),只有混合运算的时候才进行
day4
运算符
单算移关与,异或逻条赋
算术运算符
++在前:先自加,在赋值
++在后:先赋值,在自加
逻辑运算符
表达式1 && 表达式2
&&截断法则:有一个为假,结果为假,前一个为假,后面就不在进行运算了
表达式1 || 表达式2
||截断法则:有一个为真,结果为真,前一个为真,后面就不在进行运算了
sizeof运算符
求内存空间大小
Sizeof(数据类型) sizeof(变量名)
位运算符
与运算(&)
都为1,才为1,有一个为0,就为0;
或运算(|)
都为0,才为0,有一个为1,就为1;
取反
0变1,1变0
~(1010 1001)----0101 0110
左移右移
简记:分有符号数和无符号数,有符号数的负数的右移是低位丢弃,高位补1,除了这个其他的都是补0。
原码: 1 000 0100
反码: 1 111 1011
补码: 1 111 1100
右移: 1 111 1111
反码: 1 000 0000
补码: 1 000 0001------------- -1
输入输出
输出:
字符型:c%
浮点型:
%e以指数形式进行输出。
%g:自动选择小数和指数中比较合适(比较短)的一种进行输出。
%m.nf .n保留小数点后n位进行输出,m指定输出域宽,(m>0)右对齐,(m<0)左对齐
,m的值如果大于数据的实际长度,左边补空格,否则原样输出!
输入:
%*c *代表抑制符 (%*nc:抑制n个字符)
字符的输入输出
字符的输入函数
getchar();
返回值:输入的字符的ascii值
getchar():单独成行的作用,吃掉垃圾!
字符的输出函数
putchar(ascii值)
day5
选择结构
switch(表达式)
{
case 标号1:
语句1;
。
。
case 标号n:
语句n;
default:
语句n+1;
}
注意
表达式不能为float类型
标号必须为常量
表达式==标号时,执行冒号后面的语句
表达式!=标号时,执行default后面的语句
结束:
直到switch,case语句结束!
遇到break语句结束!
循环结构
while和do...while的区别
while:先判断在执行,循环体至少执行0次
do...while:先执行在判断,循环体至少执行1次
break和continue的区别
break的作用
1、跳出switch case语句
2、跳出循环
continue的作用
跳出本次循环,进入下一次循环
goto语句
无条件跳转语句
goto 标号;
标号:
day6
数组
概念:一组数据类型相同的元素的集合
打印地址p%
定义:存储类型 数据类型 数组名[元素个数]
数组的数据类型:数据类型 [元素个数]
变量的数据类型:去掉变量名剩下的就是变量的数据类型
数组所占内存空间=sizeof(数据类型)*元素个数
数组元素个数不同,数据类型也不一样,元素个数必须是一个确定的数
数组名代表整个数组
数组名也代表数组首元素的地址
冒泡排序
思想:从左到右,俩俩依次比较,如果前一个比后一个大,交换位置,否则不变
字符数组
字符数组的本质,就是字符串,以‘\0’作为结束符
存储类型 数据类型 数组名[元素个数];
字符数组的输出函数
puts(数组名);
功能:将数组的内容输出打印到终端,并且自动添加换行
注意:遇到‘\0’结束
字符串的输入函数
gets(数组名);
功能:将键盘接收到的字符串存放到数组中,并且末尾自动添加‘\0’
注意:不会进行越界检测,所以输入的时候不用越界
总结
scanf和gets的区别
gets以回车作为结束符,scanf以回车,tab,空格作为结束符
缓存区:
gets:当完成字符串的输入后,会自动清空缓冲区的内容
scanf:当完成字符串的输入后,缓冲区会遗留空格,回车,tab
注意:
gets首先会检测缓冲区是否有内容,如果有直接拿来使用,否则输入
scanf是标准的输入函数,只能通过键入方式
printf和puts区别
puts会自动添加换行,printf不会
字符串处理函数
strlen,strcpy,strcat,strcmp
求字符串长度
strlen(数组名);
功能:求字符串的长度
返回值:求得字符串的实际长度,不包含‘\0’
sizeof与strlen区别
strlen是求得字符串的实际长度,不包含‘\0’,而sizeof是求得的整个空间的大小
sizeof是运算符,strlen是库函数
字符串的拷贝函数
strcpy(数组1,数组2/字符串2);
功能:将2的内容拷贝到1中,包含‘\0’,相当于完全拷贝
注意:数组1的容量大于数组2的
strncpy(数组1,数组2/字符串2,n)
功能:将数组2的前n个字符拷贝到数组1中
注意:拷贝的字符不包含'\0'
字符串的连接函数
strcat(数组1,数组2/字符串2);
功能:将数组2或者字符串2的内容连接到数组1中,数组1的’\0’会被覆盖
注意:数组1容量足够大
strncat(数组1,数组2/字符串2,n);
功能:将数组2的前n个字符连接到数组1中
字符串的比较函数
strcmp(数组1/字符串1,数组2/字符串2);
功能:比较字符串1和字符串2的大小
返回值:
大于0:字符串1>字符串2
等于0:字符串1==字符串2
小于0:字符串1<字符串2
比较规则:
从左到右依次对字符串的ASCII码进行比较,直到遇到不同的,或者遇到’\0’结束
二维数组
数组:一组数据类型相同的元素的集合
整型数组:一组int型数集合在一起
字符数组:一组char型字符集合在一起
二维数组:一组(数组类型的)元素集合在一起
定义
存储类型 数据类型 数组名[元素个数];
存储类型 数据类型 数组名[行数][列数];
行数:有几个一维数组
列数:一维数组中有几个元素
Int a[2][3];//定义了一个二维数组,数组长度为2,每一个元素又是长度为3的int型数组
二维数组的行数可以省略,列数不可以省略,因为列数可以确定每一个一维数组有几个元素,行数不行
day7
二维字符数组
Char str[30] = “hello”;
Scanf(“%s”,str);
Printf(“%s\n”,str);
存储类型 数据类型 数组名[行数][列数];
行数:(一维字符数组的个数)字符串的个数
列数:(一维字符数组中字符的个数)每一个字符串最多存放几个字符
Char str[3][20];//定义了一个长度为3的数组,每一个元素又是长度为20的字符数组
函数
自定义函数
存储类型 数据类型 函数名(形式参数列表);
{
函数体;
返回值;
}
存储类型:auto,static,extern,register
数据类型:返回值的数据类型
函数名:见名知意
形式参数列表:要实现的功能所需要的参数,需要调用者自己传入(1.需要几个2.每个参数的数据类型)
函数体:具体实现的功能
返回值:如果没有返回值,可以省略,不需要写return,数据类型 void,如果有,有且仅有一个
调用函数
函数名(实际参数列表);
注意:
- 需要将实参的值传递给形参,实参的个数和数据类型必须和形参保持一致
- 实参可以是变量,常量,表达式,必须是一个确定的值
- 实参和形参是俩快独立的内存空间
- 传参实际上是将实参的值拷贝给了形参
- 形参是局部变量,在函数调用的时候被定义,函数调用结束,释放空间
函数声明
帮编译器做语法检查
指针
什么是指针
指针是一种数据类型,是一种保存地址的数据类型。
int a;//int:用来保存整型数的数据类型
char b;//char:用来保存字符的数据类型
float c;//float:用来保存浮点型数的数据类型
指针 d;//指针:用来保存地址的数据类型
什么是地址
内存分配的最小单位是字节,每一个字节都有一个编号,我们把这个编号叫做地址
地址的本质:内存单元的编号
指针:指针就是地址
指针的本质:内存单元的编号
指针变量
int a;//整型变量
float b;//浮点型变量
char c;//字符型变量
指针变量:专门用来存放地址(内存单元的编号)的变量
指针的定义
存储类型 数据类型 *指针变量名;
int *p;
存储类型:auto,static,register,extern
数据类型:指针所指向的数据类型(去掉*和变量名,剩下的就是指针所指向的数据类型)
指针的数据类型:数据类型 *//int *
在C语言中,*的三种用法
1、作为双目运算符,表示乘法5*6
2、在定义变量的时候使用,表示指针这种数据类型
3、作为单目运算符,表示取值
在32os,所有的指针占4字节
在64os,所有的指针占8字节
指针赋值
char *p = &a;
char *p = NULL;
p = &a;
注意:对指针赋值时,一定要注意数据类型匹配
思考:
1、什么是指针
是一种数据类型,是一种保存地址的数据类型
2、地址是什么
字节(内存单元)的编号
3、什么是指针变量
专门用来保存地址(内存单元编号)的变量
4、指针变量如何定义
存储类型 数据类型 *指针变量名;
5、指针变量赋值后能干啥
指针指向谁,保存的就是谁的地址,赋值后就可以操作地址里面的元素
空指针和野指针
空指针:
没有指向的指针(值为0的指针,就认为该指针没有指向)
注意:0号地址,禁止操作,要操作只能改变指针的指向
野指针:
不知道指向那里的指针
局部变量没有初始化,其值为随机值
局部指针变量没有初始化,就是野指针
如何避免野指针出现?初始化为NULL
int *p = NULL;
值传递和地址传递
printf右结合
首先:a++,第四位输出定格在2,a=3
其次:a,第三位输出不能确定,a=3
然后:++a,此时a=4,但是第二位还是不能确定
最后:a++,第一个先赋值确定为4,a=5,第二位和第三位为5才可以确定
总结:先赋值的第一次就可以确定,后赋值的要等运算结束,才能确定。
day8
二级指针
1.1概念
指针的指针
二级指针他的内存空间存放的就是一级指针的地址
1.2定义
定义一级指针:存储类型 数据类型 *指针变量名;
数据类型:指针指向的数据类型int *p;
存储类型 数据类型 **指针变量名;
总结:
1、指针的数据类型,去掉变量名剩下的就是
Int *p;//int *
Int **pp;//int **
Int ***ppp;//int ***
2、指针指向的数据类型,去掉一个*和变量名剩下的就是所指向的数据类型
Int *p;//int
Int **pp;//int *
Int ***ppp;//int **
3、指针所能访问到的空间大小,由指针指向的数据类型来决定
(1)int a;
Int *p = &a;//*p所能访问的空间大小为4字节
(2)char b;
Char *p = &b;//*p所能访问的空间大小为1字节
(3)int *p;
Int **pp = &p;//**pp所能访问到的空间大小为4字节
指针的算数运算
总结:
p+n:p+n相对于p向地址增大的方向移动了n个数据
实际的变化:p+sizeof(指向的数据类型)*n
p-n:p-n相对于p向地址减小的方向移动了n个数据
实际的变化:p-sizeof(指向的数据类型)*n
p++:p向地址增大的方向移动了一个数据
p--:p向地址减小的方向移动了一个数据
p-q:(p和q的数据类型必须一致)这俩个指针之间相隔的个数
实际的变化:(p-q)/sizeof(指向的数据类型)
注意:
- 指针的算数运算只有在操作连续的内存空间时才有意义
- p是指针变量,以上的方法也适用于常量,但是++,--除外
(数组名:1.数组首元素地址(指针常量))
指针和一维数组
指针常量访问
数组名:指针常量不能进行++,--
指针变量访问
以下三种情况也当作指针来处理,大小8字节(64os)
day9
指针和二维数组
int a[2][3] = {0};
&a, a, &a[0], a[0], &a[0][0]
&a:a当作整个数组,整个数组的地址就是首地址
a:代表首元素地址,a[0]的地址
&a[0]:二维数组首元素的地址(对第一个一维数组整个进行取地址)
a[0]:代表第一个一维数组中首元素的地址,a[0][0]的地址
&a[0][0]:第一个一维数组首元素的地址
一维数组给予参考
Int a[0];
&a:对整个数组取地址
a:代表首元素地址,a[0]地址
&a[0]:首元素地址
总结:
1、a, &a[0], &a[0][0]值一样,意义完全不一样
a:int(*)[3]:指向一维数组的指针 a[0]:int *:指向一个整型变量 a[0][0]:int 类型
2、为什么不是int **?
a+1移动了12byte,如果是int **,加1,移动4byte
3、a指向a[0],a[0]又是一维数组,所以说a指向了一个一维数组
数组指针和指针数组
数组指针
概念:
指向数组的指针
定义:
存储类型 数据类型 (*指针变量名)[元素个数];
存储类型:auto,static,extern,register
数据类型:数组指针指向的数组中元素的数据类型
数组指针的数据类型:数据类型 (*)[元素个数]
元素个数:指针所指向的数组中的元素个数
int a;//数据类型 int
int *p;//数据类型 int *
p = &a;//一个指向整型变量的指针
int a[5] = {0};//数据类型 int [5]
int (*p)[5] = NULL;//int (*)[5] 数组指针指向整个数组
p = &a;//a相对于整个数组
数组指针和一维数组
注意:数组指针,几乎不操作一维数组,更多操作的是二维数组,因为指针访问连续的内存空间时才有意义,如果是一维数组,p+1就会越界!!!
数组指针和二维数组
int a[2][3] = {0};
int (*p)[3] = NULL;(p = &a[0],&a[0]就是二维数组的数组名a)
p = a;(&a[0])
//之前int a[5];int *p = a; a,首元素地址,定义了一个指针也指向了这个首元素
//现在,首元素为一维数组,a指向首元素地址,首元素是一维数组,a是数组指针
定义一个数组指针,也指向二维数组首元素,首元素为数组
指针数组
概念:
元素为指针的数组
定义:
存储类型 数据类型 *数组名[元素个数];
数据类型 *:数组中元素的数据类型
int *arr[3];
定义了一个数组,数组名叫arr,有三个元素,每一个都是int *类型
指针数组和二维指针
day10
const修饰的指针
const:只读
const用来修饰变量。修饰的变量只能读,不能写。
const修饰的指针
- const int *p = &a;//const修饰值,*p不能改变
- Int *const p = &a;//const修饰地址,p指向不能改变
- Const int *const p = &a;//修饰值和地址,*p和p都不能改变
int const *p;
左值右址
Const在*左边,*p不能被改变
Const在*右边,p不能被改变
指针变量:专门用来保存地址的变量
指针常量:int *const p //修饰地址的,p的指向不变
常量指针:const int *p //修饰值的,值不变
main函数传参
以上就是我参与培训的C语言内容!