目录
一、指针变量初始化
如果指针变量没有初始化,此时是随机值。 ---野指针
初始化可以让指针变量 有明确指向。
int a = 10;
int *p = &a;
int *p = NULL; //NULL 0号地址 --- 空指针
赋值:
int * p;
p = NULL;
int a;
int *p;
p = &a;
定义多个指针:
int *p,q; //p是指针类型 int *
//q是int型
int *p,*q; //此时表示定义了两个 int*类型的变量 p 和q
//注意:定义时候的 * 修饰变量名的 表示定义的是一个指针类型的变量
二、指针的作用
通过指针可以让被调修改主调
要实现被调修改主调:让指针作为函数参数
形参 -- 指针类型变量 ,用来接收实参 (实参是要操作的内存空间的地址)
实参 -- 要修改谁,就把谁的地址传过去
//注意:要保证空间有效,也就是不能是野指针;被调函数中 一定要有 *p 运算 //(间接访问的操作)
值传递 //只是将实参数据赋值给了形参
地址(指针)传递 //传的是地址 --可以实现被调修改主调
通过指针求两个数的和
#include <stdio.h>
void add(int a,int b,int *sum)
{
*sum=a+b;
}
int main(void)
{
int m,n;
scanf("%d %d",&m,&n);
int sum=0;
add(m,n,&sum);
printf("add=%d\n",sum);
return 0;
}
通过指针在函数中修改了主函数的sum的值,也就是背调修改主调
注意在函数传参时,考虑哪些变量是值传递,哪些变量是地址传递,需要修改的变量使用地址传递,也就是指针;不用修改的使用值传递。
三、指针 + 一维整型数组
int a[5]; //一维整型数组
//数组名a
类型 --- 数据类型 int[5]
值 --- 数组首元素的地址 --- 常量
//数组名是个常量,不能做自增自减运算
让指针指向数组,就是指向数组首元素的地址
int *p = &a[0];
由于数组名的值就是首元素的地址,所以指针指向数组写成:
int *p = a;
所以a <=> &a[0]
//a[0]的数据类型 -- int型
//&a[0] 地址的类型 -- int *
int *p = a; //表示 p指向数组a
*p <=> a[0]
想要访问数组中首元素后的元素通过*(p+i)
因为*p等价于a[0]所以*(p+i) <=> a[i] <=> *(a+i)
由此推出a[i] <=> i[a]
a[i] <=> *(a+i)
i[a] <=> *(i+a)
#include <stdio.h>
void printfArray(int *a,int len)
{
int i=0;
for(i=0;i<len;++i)
{
//printf("a[%d]=%d\n",i,a[i]);
//printf("a[%d]=%d\n",i,*(a+i));
//printf("a[%d]=%d\n",i,i[a]);
printf("a[%d]=%d\n",i,*a++);
}
}
int main(void)
{
int a[]={1,2,3,4,5,6,7,8};
printfArray(a,8);
return 0;
}
四种方式都可以打印出数组各元素,数组名是不能自增的,但是这里的a++是指针运算,因为函数的形参中是int *a,是指针变量。
由于++和*的运算优先级相同,看结合性,是自右向左的,所以++会先运算,a++先用后加,所以是从a[0]元素开始打印的。
数组作为函数参数
形参 -- 数组形式 //本质上是一个指针类型变量int *a
数组长度 int len
实参 -- 数组名 //数组名代表数组首地址
数组长度
四、指针的运算
& 取地址符号
* 指针运算符
*&p //实际上就是p,*与&的作用相互抵消掉了
//类型int* *(指针的指针)
#include <stdio.h>
int main(void)
{
int a=10;
int *p=&a;
printf(" &a=%p\n",&a);
printf("*&a=%d\n",*&a);
printf(" p=%p\n",p);
printf("*&p=%p\n",*&p);
printf("&*p=%p\n",&*p);
return 0;
}
可以看到,&a,p,*&p,&*p的值相同,而*&a就是a,由此可以看出*与&的作用相互抵消掉了。ps:不能进行&*a这样的运算,因为a是个int型变量,不是指针变量,不能进行指针运算。
p+1 //加n 表示 跳过了n个基类型
p-1
p++
p--
指针比较 > >= < <= == !=
p - q //表示差了多少元素(基类型)
//注意必须是同一类型的指针
p + q //没有实际含义,不允许这样运算 ,同理乘法和除法也不行
通过迭代的方式实现数组逆序
#include <stdio.h>
void printfArray(int *begin,int *end)
{
while(begin<=end)
{
printf("%d ",*begin++);
}
putchar('\n');
}
void reverse(int *begin,int *end)
{
while(begin<end)
{
int temp=*begin;
*begin=*end;
*end=temp;
begin++;
end--;
}
}
int main(void)
{
int a[]={1,2,3,4,5,6,7,8};
int len=sizeof(a)/sizeof(a[0]);
printfArray(a,a+len-1);
reverse(a,a+len-1);
printfArray(a,a+len-1);
return 0;
}
通过指针实现选择排序
#include <stdio.h>
void printfArray(int *begin,int *end)
{
while(begin<=end)
{
printf("%d ",*begin++);
}
putchar('\n');
}
void choose(int *begin,int *end)
{
int *p=begin;
int *q=NULL;
for(p=begin;p<end;++p)
{
for(q=p+1;q<=end;++q)
{
if(*p>*q)
{
int temp=*q;
*q=*p;
*p=temp;
}
}
}
}
int main(void)
{
int a[]={4,5,6,2,3,8,1};
int len=sizeof(a)/sizeof(a[0]);
printfArray(a,a+len-1);
choose(a,a+len-1);
printfArray(a,a+len-1);
return 0;
}
通过指针实现冒泡排序
#include <stdio.h>
void printfArray(int *begin,int *end)
{
while(begin<=end)
{
printf("%d ",*begin++);
}
putchar('\n');
}
void popo(int *begin,int *end)
{
int *p=begin;
int *q=NULL;
for(p=end;p>begin;--p)
{
for(q=begin;q<p;++q)
{
if(*q>*(q+1))
{
int temp=*q;
*q=*(q+1);
*(q+1)=temp;
}
}
}
}
int main(void)
{
int a[]={4,5,6,2,3,8,1};
int len=sizeof(a)/sizeof(a[0]);
printfArray(a,a+len-1);
popo(a,a+len-1);
printfArray(a,a+len-1);
return 0;
}
通过指针实现插入排序,以及二分查找
#include <stdio.h>
void printfArray(int *begin,int *end)
{
while(begin<=end)
{
printf("%d ",*begin++);
}
putchar('\n');
}
void insert(int *begin,int *end)
{
int *p=begin;
int *q=NULL;
for(p=begin+1;p<=end;++p)
{
int temp=*p;
q=p;
while(q>begin&&*(q-1)>temp)
{
*q=*(q-1);
--q;
}
*q=temp;
}
}
int * find(int *begin,int *end,int n)
{
int *mid=NULL;
int *ret=NULL;
while(begin<=end)
{
int *mid=begin+(end-begin)/2;
if(*mid>n)
{
end=mid-1;
}
else if(*mid<n)
{
begin=mid+1;
}
else
{
ret=mid;
break;
}
}
return ret;
}
int main(void)
{
int a[]={4,5,6,2,3,8,1};
int len=sizeof(a)/sizeof(a[0]);
printfArray(a,a+len-1);
insert(a,a+len-1);
printfArray(a,a+len-1);
int *ret=find(a,a+len-1,4);
if(ret==NULL)
{
printf("not found\n");
}
else
{
printf("%d found\n",*ret);
}
return 0;
}
通过递归实现二分查找
#include <stdio.h>
int * find_r(int *begin,int *end,int n)
{
int *ret=NULL;
int *mid=begin+(end-begin)/2;
if(begin>end)
{
return NULL;
}
if(n>*mid)
{
begin=mid+1;
ret=find_r(begin,end,n);
}
else if(n<*mid)
{
end=mid-1;
ret=find_r(begin,end,n);
}
else
{
ret=mid;
}
return ret;
}
int main(void)
{
int a[]={1,2,3,4,5,6,7,8};
int len=sizeof(a)/sizeof(a[0]);
int *ret=find_r(a,a+len-1,11);
if(ret==NULL)
{
printf("not found\n");
}
else
{
printf("%d found\n",*ret);
}
return 0;
}
快速排序
#include <stdio.h>
void swap(int *a,int *b)
{
int temp=*a;
*a=*b;
*b=temp;
}
void quickSort(int *begin,int *end)
{
int *p=begin;
int *q=end;//记录起始位置
if(begin>=end)
{
return ;
}
int *k=begin;
while(begin<end)//相遇时停止
{
while(begin<end && *end>=*k)
{
end--;
}
while(begin<end && *begin<=*k)
{
begin++;
}
swap(begin,end);
}
swap(k,begin);
quickSort(p,end-1);//左半部分
quickSort(begin+1,q);//右半部分
}
void printfArray(int *begin,int *end)
{
while(begin<=end)
{
printf("%d ",*begin++);
}
putchar('\n');
}
int main(void)
{
int a[]={3,4,2,6,7,5,9};
int len=sizeof(a)/sizeof(a[0]);
printfArray(a,a+len-1);
quickSort(a,a+len-1);
printfArray(a,a+len-1);
return 0;
}