011-指针(上)-C语言笔记
学习目标
1.【掌握】字符串常用函数
2.【掌握】指针变量的声明
3.【掌握】指针变量的初始化
4.【掌握】函数与指针
5.【掌握】指针的数据类型
6.【掌握】多级指针
7.【掌握】指针与数组
一、字符串常用函数
puts和gets函数的声明在stdio.h头文件中,strcmp、strlen、strcpy、strcat函数的声明在string.h头文件中。
puts()函数
语法:puts(存储字符串数据的数组名);
输出一个字符串数据,并自动换行。不过只能输出字符串,并且不能使用格式控制符。
1
2
3
|
#include <stdio.h>
charname[]="jack";
puts(name);//输出name字符数组里的字符串数据
|
gets()函数
语法:gets(存储字符串数据的数组名);
从控制台接收一个字符串数据,并存储在制定的字符数组之中。并且能读取到空格,scanf不能读取。不过gets只能接收字符串。无论是gets函数还是scanf函数在接收字符串的时候都是不安全的。如果输入字符串长度不够的时候,就会出问题。
1
2
3
|
#include <stdio.h>
charname[20];
gets(name);//接收20个字符内的字符串数据存储到name里
|
strcmp()函数
语法:strcmp(字符串1,字符串2);//返回int类型
根据每个字符对应的ASCII码依次比较两个字符串的每个字符的大小,如果比较到两个字符不同,就返回结果。如果返回正数,说明第一个字符串大,返回负数,说明第二个大。返回0,说明每个字符的ASCII相同。
1
2
3
4
5
|
#include <string.h>
charname[]="afdaf";
charname1[]="adfdg";
intcmp=strcmp(name,name1);//比较两个字符串的大小
printf("cmp = %d
",cmp);//打印len = 5
|
strlen()函数
语法:strlen(字符串);
计算字符串的长度,一个一个字符计数,直到遇到' '为止。返回值是unsigned long。
1
2
3
4
|
#include <string.h>
charname[]="afdaf";
unsignedlonglen=strlen(name);
printf("len = %d
",len);//打印len = 5
|
strcpy()函数
语法:strcpy(字符串1,字符串2);
将字符串2拷贝到字符串1里,并且覆盖掉字符串1里的数据。如果字符串1放不下字符串2,就会保错。
1
2
3
4
5
|
#include <string.h>
charname[]="afdaf";
charname1[]="adfdg";
strcpy(name,name1);//会覆盖掉name
puts(name);//输出 adfdg
|
strcat()函数
语法:strcat(字符串1,字符串2);
将字符串2中的数据追加到字符串1后面,不会覆盖,只会拼接。如果字符串1放不下字符串2,就会保错。
1
2
3
4
5
|
#include <string.h>
charname[20]="afdaf";
charname1[]="adfdg";
strcat(name,name1);//不会覆盖掉name,只是name1连接到name屁股后面
puts(name);//输出 afdafadfdg
|
二、指针变量的声明
我们声明一个变量,实际是在内存中申请一个指定字节数的字节空间来存储数据,分配变量空间的时候,是从高地址到底地址来分配的。
概念:
1.变量的值:是存储在变量空间里的数据。
2.变量的地址:声明变量时申请到的字节空间中低字节的地址。
3.指针:变量的地址就叫做指针,地址就是指针,指针就是地址,只是换了个说法而已。
4.指针变量:其实也就是一个变量,只不过这个指针变量的值是个地址。
访问变量的两种方式:
1.直接访问:直接使用变量名来访问。
2.间接访问:让一个指针指向这个变量,通过这个指针可以间接的访问这个变量。
指针变量的声明
语法:
声明普通变量:数据类型 变量名;
声明指针变量:数据类型 *指针变量名;
1
2
3
|
int*p;//表示我们声明了一个指针变量,名字叫p,*只是说明这是一个指针变量,而不是普通变量。
int*p1;//*的位置可以挨着数据类型,也可以单独空一格
int*p2;
|
注意:
1
2
3
4
|
int*p3;//*在这里只是说明这是一个指针变量,而不是普通变量。
int*p4;//p4只能存储int类型的变量的地址
float*p5;//p5只能存储float类型的变量的地址
double*p6;//p6只能存储double类型的变量的地址
|
指针变量名也是一个标识符,也需要符合变量的命名规则和规范。一般情况下,我们变量名都以p开头,这样让别人一眼都能看出是指针变量。
1
2
|
int*p1,p2,p3;//是错误的,这样声明的只有p1才是指针变量,p2,p3是int类型普通变量
int*p1,*p2,*p3;//这才是正确的。
|
三、指针变量的初始化
指针变量中只能存储和指针变量类型相同的变量的地址,所以不能直接给指针变量赋值一个其他非地址的数据。使用&取地址运算符可以获取变量的地址。
语法:数据类型 *指针变量名 = 相同数据类型的变量的地址;
1
2
3
|
intnum=10;
int*p=#//获取num的地址并赋值给指针变量p
int*p1=p;//将p中存储的值赋值给新声明的指针变量p1。等价于 int *p1 = #
|
通过指针变量访问指针变量指向的普通变量,使用*取值符来取出指针变量指向的普通变量。
1
2
3
4
|
intnum=10;
int*p=#//将num的地址赋值给指针变量p
*p=20;//把20赋值给了p指向的num,这里的*p表示取出指针(p)的值(num的地址)的变量(num变量)。
printf("num = %d
",num);//打印 num = 20
|
注意:
野指针:声明一个指针变量而没有初始化,这个指针变量的值是一个随机内存地址。通过这个指针去为指针指向的空间赋值的时候,就有可能改掉别人的数据,造成崩溃。
空指针:声明一个指针变量的时候不确定指向哪个变量,可以给他赋值NULL或者0(这里0就代表NULL,不是整型0),代表这个指针不指向任何空间。
四、函数与指针
在函数中操作实参
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
|
#include <stdio.h>
//计算最大值、最小值、平均值、高级平均值
voidgetMaxAndMin(intarr[],intlength,int*max,int*min,int*sum,float*avg,float*avg2);
//改变实参数据
voidziZeng(int*num);
intmain(){
intarr[]={1,2,3,4,5,6,7};
intlength=sizeof(arr)/sizeof(int);
intmax=arr[0],min=arr[0],sum=0;
floatavg=0.0f,avg2=0.0f;
//调用函数
getMaxAndMin(arr,length,&max,&min,&sum,&avg,&avg2);
printf("max = %d min = %d sum = %d avg = %.2f avg2 = %.2f
",max,min,sum,avg,avg2);
intnum=1;
ziZeng(&num);
printf("num = %d
",num);
}
//计算最大值、最小值、平均值、高级平均值
voidgetMaxAndMin(intarr[],intlength,int*max,int*min,int*sum,float*avg,float*avg2){
for(inti=0;i<length;i++){
//最大值
if(arr[i]>*max){
*max=arr[i];
}
//最小值
if(arr[i]<*min){
*min=arr[i];
}
//累加和
*sum+=arr[i];
}
//平均值
*avg=(float)*sum/length;
//去掉一个最大值和一个最小值后的平均值
*avg2=(*sum-*max-*min)/(length-2);
}
//改变实参数据
voidziZeng(int*num){
for(inti=0;i<5;i++){
(*num)++;
}
}
|
五、指针的数据类型
通过指针操作指针指向的变量的时候,只能找到被指向那个变量的低字节的地址,到底要操作几个字节的空间是根据指针的类型来决定的。例如:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
#include <stdio.h>
intmain(intargc,constchar*argv[]){
charch1='a';
charch2='b';
charch3='c';
charch4='d';
int*p1=&ch4;
*p1='a';
printf("ch1 = %c
",ch1);//ch1 = 0
printf("ch2 = %c
",ch2);//ch2 = 0
printf("ch3 = %c
",ch3);//ch3 = 0
printf("ch4 = %c
",ch4);//ch4 = a
return0;
}
|
原理:这里指针操作指针指向的变量的时候,指针认为他指向的是int类型的变量,int类型占4个字节的空间,所以操作了4个字节的空间。
六、多级指针
一级指针:如果一个指针变量中存储的是一个普通变量的地址,那么这样的指针就叫做一级指针。
1
2
|
intnum=10;
int*p=#
|
二级指针:如果一个指针变量中存储的是一个一级指针变量的地址,那么这样的指针就叫做二级指针。
1
2
3
|
intnum=10;
int*p1=#
int**p2=&p1;
|
三级和多级同理。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
#include <stdio.h>
intmain(){
intnum=10;
int*p1=#//p1存储num的地址
int**p2=&p1;//p2存储p1的地址
int***p3=&p2;//p3存储p2的地址
*p1=100;//*p1取出num变量
**p2=200;//**p2取出num变量
***p3=300;//***p3也是取出num变量
printf("num = %d
",num);
printf("num = %d
",***p3);
return0;
}
|
七、指针与数组
指针可以和整数进行加减运算
1
2
3
4
5
6
7
|
charch='a';
char*p=&ch;
p++;//p的值增加了一个char类型字节数
intnum=10;
int*p1=#
p1++;//p1的值增加了一个int类型字节数
|
遍历数组大法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
|
#include <stdio.h>
intmain(){
intnum[]={1,2,3,4,5,6,7,8,9,0};
intlength=sizeof(num)/sizeof(int);
int*p=num;
//第一种,传统遍历大法
for(inti=0;i<length;i++){
printf("%d ",num[i]);
}
printf("
");
//第二种,移动地址指向 并取值来遍历
for(inti=0;i<length;i++){
printf("%d ",*(p+i));
}
printf("
");
//第三种,因为p == num,移动地址指向 并取值来遍历
for(inti=0;i<length;i++){
printf("%d ",*(num+i));
}
printf("
");
//第四种,根据每个元素的地址来获取值
for(inti=0;i<length;i++){
printf("%d ",*(&num[i]));
}
printf("
");
//第五种,根据每个元素的地址来获取值
for(inti=0;i<length;i++){
printf("%d ",*((&num[0]+i)));
}
printf("
");
//第六种,判断地址大小
for(;p<=&num[length-1];p++){
printf("%d ",*p);
}
//重置p的值
p=num;
printf("
");
//第七种,p自增
for(inti=0;i<length;i++,p++){
printf("%d ",*p);
}
//重置p的值
p=num;
printf("
");
//第八种,p自增
for(inti=0;i<length;i++){
printf("%d ",*(p++));
}
//重置p的值
p=num;
printf("
");
return0;
}
|
指针数组:
所谓的指针数组,指的是一个专门用来保存多个相同数据类型指针的数组。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
#include <stdio.h>
intmain(intargc,constchar*argv[]){
intnum1=10;
intnum2=20;
intnum3=30;
int*p1=&num1;
int*p2=&num2;
int*p3=&num3;
int*arr[]={p1,p2,p3};
int**p4=arr;
for(inti=0;i<3;i++){
printf("%d
",**(p4+i));
}
return0;
}
|