------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------
一、指针
1,指针变量概念机定义方法
指针变量: 在c语言中,允许用一个变量来存放指针,这种变量称为指针。
严格意义说,指针式一个地址,是一个常量,指针变量事存放一个地址,事一个变量
2定义一个指针变量
指针类型说明,即定义变量为一个指针变量;
指针变量名
指针值(指针)
一般形式 类型说明符 *变量名
int *p 定义了一个指针变量,变量名是p
int,表示p只能存放一个int 类型的变量的地址
3指针变量的定义的注意:
1"*" 必须得有如果没有就相当于定义一个普通变量
2指针变量 不能 用来存放数值或者名符之类
3指针变量,归根到底还是变量也有全局变量和局部变量之分
4指针变量的初始化
指针变量也是变量
指针变量的使用:定义指针变量 》初始化指针变量》使用
完全初始化
1)定义的同时初始化
int *p =&a ;
2)部分初始化
int *p=&b,*P4;
p4=&c;
2)定义后初始化
int *p2;
p2 =NULL; //是空
3)定义了一个指针变量,不知道指向谁
int *P8=NULL;
int *p6 = 0; //把一个指针定义为空,就是什么也不指向。
指针变量的作用:获取指针变量指向的内存空间的内容
获取指针变量值所对应的存储单元
”*“ 的两种用法
1用来定义一个指针变量
2获取值 *p 获取p指向的变量地址的值
4)指针变量不初始化有什么后果
如果不初始化 这个指针变量放的就是垃圾值,这个指针就叫野指针。
5.用函数交换两个变量的值
void swap(int a,int b){
int temp=0;
tmp =a
a=b;
b=temp;
} 在函数中这个只是函数的形参变了
正确的是用指针
#include
void swap1(int*p,int*p1){
int *temp;
temp =p;
p=p1;
p1=temp;
}
int main(int argc,const char *argv){
int a=a4,b=5;
printf("交换前a=%d,b=%d\n",a,b);
swap1(&a,&b);
printf("交换后的值 a=%d, b=%d\n",a,b)
return 0;
}
7,指针的应用场景
1)在被函数中可以修改主函数中的变量之值。
void changValue(int*p){
*p =10;
}
int main( int argc ,const char*argv[]){
int a=10;
int *P1 =&a //p1指向了a
printf("%d\n",*p1);//a=10
change(p1);
printf("%d\n",*p1);//100
printf("%d\n",a);//100
returen 0;
}
2)实现多个返回值
void caculator(int x, inty,int*add,int*jian,int*cheng,double*chu){
*add = x+y;
*jian =x-y;
*cheng = x*y;
*chu = x /(double)y;
}
int main(int argc,const char*argv[]){
int add;
int jian;
int cheng;
int chu;
caculator(3,4,&add,&jian,&cheng,&chu);
printf("add=%d,jian=%d,cheng=%d,chu=%d",add,jian,cheng,chu);
return 0;
}
8 二级指针
如果一个指针变量存放的是另一个指针变量的地址,则称这个指针变量为指向指针的指针变量,也就是“二级指针”
定义一个二级指针 int **p =&p
int a =10;
int *p =&a; p的值时a的地址
int**p=&p; **p 就是取出 p里面存储的地址,而p存的是&a的地址,就是a的值
9 指针为什么要区分类别
不同类别表示职能存不同的类型的地址
int *p 便是指针职能存放int类型的地址
int a=5;
char *p=&a; a占四个字节,而这里每次只取一个字节。数据会改变
所以是什么类型的变量 就用什么类型的指针
二、指针与数组
1 数组指针;
指针变量可以指向数组的某个元素(把某一元素点地址放到相应的地址)
所谓数组元素的指针就是数组与元素的地址
指针数组的作用: 使用数组指针间接访问数组的元素
数组指针的定义:int *p 和定义变量指针一样
数组指针的初始化
int a[4]={1,2,3,4};
int *p=a //数组指针,定义了一个指针变量p赋值数组的首地址(第一个元素到地址),p指向数组的第一元素
int *p =&a[0]//等价上面一句话。
2.数组指针的用法
数组指针如何访问数组的元素:
p+1 表示指向数组的下一个元素
p-1表示指向数组的上一个元素
也可用*p++ 是个指针变量,是变量所以也可以++
int a[5]={1,2,3,4,5};
int*p =a;//表示p指向数组的第一个元素
*(p+1) = a[1];
使用数组指针和使用数组名的区别
用数组指针遍历数组
for(int i=0;i<4;i++){
printf("%d\t",*p++); //p指向数组的首元素
}
数组名a是一个常量不能++
总结:
引用一个数组元素,可以用两种方法
1下标法 如a[i]形式
2指针法如*(a+i)或*(p+i)
3a是常量(a++是错误的),p是变量(p++正确)
3.一维指针数组
一个数组的元素值为指针则是指针数组。白话存放指针的数组,就是指针数组
指针数组的一般形式 类型说明符*数组名[数组长度]
类型说明符为指针说指向的变量的类型
int *p[3]
表示p时一个指针数组,它有是三个元素,诶个元素都是一个指针,指向整型变量。
指针数组的使用 int p*[3]={&a,&b,&c};
p[0] =&a; a的地址 p数组的首地址
p就是指针数组的地址 访问a 的值 *(p[0])
4.指针变量之间的运算
两个指针之间的减法运算,
1》 0x0006 -0x003 =3(意义不大)
2》常见的用法: 两个指针指向同一个数组
判断两个指针变量指向的元素是否连续
判断两个指针变量之间相隔几个元素
int a[5]={2,3,4,5,6};
int *p=a;//p指向了数组的书元素
int *p1 =&a[3]; p1指向了数组的第四个元素
//地址值(p1-p)/sizeof(int)
printf("p1 - p =%d\n",p1-p);
如果两个指针变量指向同一个元素 那么他们相减等结果时0
判断两个指针变量指向的元素是不是相邻,如果相邻他们相减的结果 绝对值为1
两个指针之间的运算关系 p1 >p == 1 表示的是p1在高位值
p1 >p ==0 表示p在高位
注意:两个指针之间没有加法。
5用数组名访问二维数组
int a[3][4]={1,2,3,5,7},{9,11,13,15},{17,19,21,23};
a代表地0行点首地址 a+1表示第一行首地址 a+2表示第二行的首地址,所以a+i代表行号
a[0] 表示第0行第0列第一个的地址,a[0]+1表示第0行第1列第一个的地址 a[0][j]表示第0行第j列的第一个的地址
15 普通指针访问二维数组
int a[2][3]={1,2,3,4,5,6};
int *p =a;
for (int i =1; i< 6;i++){
printf("%d",*p++);
}
这里是应为数组他排列示在内存是这样的。
1
2
3
4
。。
说一可以写成*p++
6二维数组指针
行指针 ,用来表示指向二维数组的每一行,存放的是首地址
定义格式:数据类型 (*行指针变量名)[数组的第二维的长度];
二维数组指针的初始化
int a[2][3];
// a= &a[0] = a[0] == &a[0][0]
首行第一个元素的地址 ,首行地址 ,首行首列元素地址 都可以表示位二维数组的地址
int (*p)[3]=a;
二维指针的使用
*(*(a+i)+j)//就是获取二维数组的每一个元素
二维数组指针遍历数组
#include
int main(int argc, const char * argv[]) {
int a[2][3] = {{1,2,3,},{4,5,6}};
int (*p)[3] = a; //二维数组指指针 p可以代替数组名a来用
//数组的遍历
for (int i =0;i<2;i++){
for (int j=0; j<3; j++) {
printf("%d\t",*(*(p+i)+j) );// *(*(a+i)+j)
}
return 0;
}
7 指针数组和二维数组指针的区别
两者都可以用来表示二维数组 但是便是方法和意义不同
int *p[3]={&a,&b,&d};p是一个指针数组
//表示配饰一个指针数组,有三个下标为p[0];p[1];p[2];均为指针变量
int *p[2]={a[0];a[1]};
int (*p)[3];//二维数组指针 表示一个指向二维数组的指针变量
四、 字符串指针
字符串指针指向 字符窜
char *变量名=" 字符串";//”字符串内容“是常量
char *str="wearefamily" 这个字符串是存储在常量去的
str只是保存了字符串常量的首地址。 指针变量都是占8个字节的
str是指针变量 ,str 还可以指向别的字符串常量 当指向"hahha"
这时str保存的是"hahha"
读取字符串的某个字符
prinf("%c\t",*(str+2))
for (inti =1;i printf("%c\t" *(str+i) ); } *(str+2)='x';错误。应为字符串常量是在常量存储区的,保存在常量区保存的数据都是只读 不能修改。 char*str2 ; scanf("%s",str2);z这样不能写应为str2 没有赋初始值 ,为野指针 可以这样定义int *str2= NULL; //空的意思 str2=malloc(100);者句话作用是先给申请一个100自己度内存str2 char 型指针数组 和字符数组的区别 二维字符数组 char ch[3][4]+{{},{}<{}}; 或者 char ch3[3][5]={"abc","cdf","sdsa"} //可以存储多个字符串 //第一维存的事字符串的首地址 //每个字符串的长度,不能超过二维长度。 char 类型的指针数组 char *name[3]={"asdad","adadsadf","qwqewqeq"}; 遍历 for (int i=1;i<3,i++){ printf("%s",name[i]) } char ch[]="abc"; 这是存储在栈区 字符指针和字符数组 字符指针 char *ss ="abc"; ss 是一个指针变量 ,指向可以改变 ss = "helloword"; 字符数组 char s1[3]= "abc"; s1是个常量,不能被赋值 。 应用字符串排序。 五、指针与函数 1.指针函数 概念 指针函数就是一个函数返回的事一个指针(即地址)这中国返回指针值的函数就叫指针函数 2定义 类型说明符 *函数名(形参){ 函数体 return 地址 } 在函数名前加了一个"*" 表示这是一个指针函数 ,即返回值是一个指针,类型说明符表示返回的指针指向的数据类型 int *max(int x,int y){ return x>y ? &x:&y; } int *max1(int *x,int *y){ return *x > *y? x : y; } int main(int argc,const char*arv[]){ int a =3,b=4; printf("a =%p\n",&a); printf("b = %P\n",&b); int *p=max(a,b); 这里传进去后只是返回到形参的值。形参变量事新分配空间 int *p1=max1(&a,&b);这里才是实参的改变 ,变量没有新分配空间只是形参和实参的地址传递 } 2 函数数的指针 在c语言中 ,函数名就是该函数所占内存区的首地址, 这个函数点首地址赋给一个指针变量,使该指针变量指向改函数。然后可以找到并调用这个函数,把这种指向函数的指针变量称为“函数指针变量” 函数指针变量:存放函数的首地址的指针变量就是函数指针变量 函数指针变量的定义 (*变量名)(函数的参数); 函数的声明 : int sum(int a,int b);------->函数指针int (*p)(int a,int b); 这里定义了一个函数指针p1 ,p1可以存放返回值是int类型,并且有两个形参 还都是int类型的函数地址 p1 = sum ;//sum存的就是函数在内存中的首地址 int sum (int a,int b){ return a+b ; } int main(){ int a =4,b=5; int (*p)(int,int);//定义函数指针 ,定义指针函数的时候可以不用写行参名 p =sum ;//初始化 sum 函数的首地址 } 3. 函数指针调用函数 #include int sum (int a,int b){ return a+b; } int main(int argc, const char * argv[]) { 指针函数的使用 //定义一个指针函数 int (*P)(int,int); //给函数指针初始化 p=sum; //用函数指针间接调用函数 int s= p(23,45); printf("%d",s); return 0; } 应用字符串排序。
#include
应用 通过指针输入1到7 到数字 输出对应的星期名
#include