------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 <stdio.h>
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 <stdio.h>
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<strlen(str;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是个常量,不能被赋值 。
应用字符串排序。
应用字符串排序。
#include <stdio.h>
#include <string.h>
void sortString(char*arry[],int length);
int main(int argc, const char * argv[]) {
//定义char类型的指针 来存储临时的地址
char *name[]={"CHINA","AMERICA","AUSTRALIA","FRANCE","GERMAN"};
sortString(name, 5);
return 0;
}
void sortString(char*array[],int length){
char *temp;
for(int j=0;j< length-1;j++){
for (int i=0;i< length-1-i;i++){
//比较两个字符串的ascii的大小
if (strcmp(array[i],array[i+1]) >0){
//实现array[i]和array[i+1]地址的交换
temp = array[i];
array[i]=array[i+1];
array[i+1]=temp;
}
}
}
for (int i =0; i<length; i++){
printf("%s\n",arry[i]);
}
}
五、指针与函数
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);这里才是实参的改变 ,变量没有新分配空间只是形参和实参的地址传递
}
应用 通过指针输入1到7 到数字 输出对应的星期名
#include <stdio.h>
char * getWeekday(int n);
int main(int argc, const char * argv[]) {
printf("%s\n",getWeekday(1));
return 0;
}
char * getWeekday(int n){
char * weekday[]={
"星期一",
"星期二",
"星期三",
"星期四",
"星期五",
"星期六",
"星期日",
};
return n<8&&n>0 ? weekday[n-1]: "输入错误!";
}
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 <stdio.h>
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;
}