初识指针 & 练习

什么是指针:

指针是一种特殊的数据类型,使用它可以定义指针变量,指针变量中存储的是整型数据,代表了内存的编号,通过这个编号可以访问到对应的内存。

为什么使用指针:

1、由于函数与函数之间是相互独立的,但是有些时候需要共享变量

​ 传参是单向值传递

​ 全局变量尽量少用,容易命名冲突

​ 使用数组还需要传递长度

​ 函数的命名空间是相互独立的,但是地址空间是同一个,所以指针可以解决这个问题

2、由于函数传参是值传递(内存拷贝),对于字节数较多的变量,值传递的效率比较低,如果传递的是变量的地址,只需要传递4|8个字节。

3、堆内存无法取名,它不像stack、bss、data让变量名和内存建立关系,只能使用指针来记录堆内存的地址编号从而使用该堆内存。

如何使用指针:

​ 定义: 类型* 变量名_p;int* p;

​ 1、指针变量与普通变量的用法上有很大的区别,为了以示区分,建议在变量名后面加上_p。

​ 2、指针的类型表示该指针变量储存的是什么类型变量的地址,指针的类型决定了可以通过指针变量访问的字节数。

​ 3、一个*只能定义一个指针变量

​ int* p1,p2,p3;(只有p1是指针,p2,p3 是int)

​ int* p1,*p2, *p3;(都是指针)

​ 4、指针变量与普通变量一样的是默认值是随机的,一般初始化为NULL

​ 赋值(引用): 变量名 = 地址;

​ 指向栈内存:

​ int num;

​ int* p = & num;

​ int* p = NULL;

​ p = & num;

​ 指向堆内存:

​ int* p = NULL;

​ p = malloc(4);

​ 解引用: *p = 1000;

​ 通过指针变量中记录的内存编号来访问对应的内存,该过程可能会产生段错误,但是原因是存储了非法的内 存编号。

​ 注意:访问的字节数是由指针变量的类型解决的。

int num = 10;
int* p = NULL;//初始化
p = #//赋址
*p = 100;//赋值
num = 100;//*p就等于num
void func(int* p)
{
    *p = 10;
    printf("%d %p\n",*p,p);
}

int main()
{
    int num = 0;
    func(&num);
    printf("%d %p\n",num,&num);
}

使用指针需要注意的问题:

空指针:

​ 值是NULL的指针变量都是空指针,如果对空指针进行解引用产生段错误

​ NULL也是一种错误标志,如果一个函数返回值是指针类型时,当函数执行出错可以返回NULL表示该函数执行 错误。

​ 注意:NULL在绝大多数的系统中都是0,在个别系统是1

​ if(NULL==p) 等价于 if(!p)

​ 如何避免空指针带来的段错误:

​ 使用来历不明的指针之前先做判断是否是空指针

​ 1、当函数的参数是指针时,别人传给你的可能就是空指针

​ 2、当函数获取返回值时,也有可能获取到空指针

野指针:

​ 指针的指向不确定的内存的指针。

​ 野指针的危害:

​ 1、段错误

​ 2、脏数据

​ 3、一切正常

​ 野指针危害比空指针更严重,因为它无法判断出来,而且可能是隐藏性的错误,短时间内不暴露

​ 如何避免:

​ 1、定义指针时一定要初始化

​ 2、函数不返回局部变量地址

​ 3、指针指向的内存被释放后,指针变量立即置空 = NULL

指针的运算:

​ 绝大多数无意义。

​ 指针+n: 指针+指针类型宽度*n

​ 指针 -n: 指针 -指针类型宽度*n

​ 指针-指针:(指针-指针)/ 指针类型宽度 计算出两个指针直接相隔多少个指针元素

指针与const

当我们为了提高传参效率而使用指针时,传参效率虽然提高了,但是变量也有被修改的风险,这种写法就可以保护指针不被修改。

const int* p; || int const* p

const 靠近谁就保护谁

int* const p;保护指针变量(地址)不被修改

const int* const p;都保护

int const * const p;都保护

练习:实现一个变量交换的函数,调用它对一个数组排序

#include <stdio.h>

void swap(int* a,int* b)
{
	int t = 0;
	t = *a;
	*a = *b;
	*b = t;
}
int main(int argc,const char* argv[])
{
	int arr[10] = {5,62,9,3,1,4,7,484,69,32};
	for(int i = 0;i<9;i++)
	{
		for(int j = i+1;j<10;j++)
		{	
			if(arr[i]>arr[j])
			{
				swap(&arr[i],&arr[j]);
			}
		}
	}
	for(int i = 0;i<10;i++)
	{
		printf("%d ",arr[i]);
	}
}

练习:实现一个函数,计算两个整数的最大公约数、最小公倍数,最大公约数用return返回,最小公倍数使用指针处理。

#include <stdio.h>

int com(int a,int b,int* p)
{
	int max = 0,min = 0;
	for(int i = 1;i <= a; i++)
	{
		if(0 == a%i && 0 == b%i)
		{
			max = i;
		}
	}
	for(int i = a*b; i >= a; i--)
	{
		if(0 == i % a && 0 == i % b)
		{
			*p = i;
		}
	}
	return max;
}
int main(int argc,const char* argv[])
{

	int a = 28,b = 7;

	int gbs = 0;

	int gys = com(a,b,&gbs);

	printf("%d %d",gbs,gys);

}
#include <stdio.h>

int com(int a,int b,int* p)
{
	if(a>b)
	{
		int t = a;
		a = b;
		b = t;
	}
	int z = a;
	int m = a,n = b;
	while(a % b != 0)
	{
		z = a % b;
		a = b;
		b = z;//辗转相除法,z就是最小公因数
	}
	*p = z;
	int x = m*n/z;
	return x;
}
int main(int argc,const char* argv[])
{
	int a = 0,b = 0;
	printf("请输入两个数:");
	scanf("%d%d",&a,&b);
	int gbs = 0;
	int gys = com(a,b,&gbs);//当需要返回两个值的时候使用指针
	printf("%d %d",gbs,gys);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值