学习C语言 8.6 指针

目录

一、指针变量初始化     

 二、指针的作用   

三、指针 + 一维整型数组 

四、指针的运算 


一、指针变量初始化     

如果指针变量没有初始化,此时是随机值。 ---野指针 
初始化可以让指针变量 有明确指向。 
    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;
	
}

  • 22
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值