C语言学习笔记——初识指针

指针的作用

1、需要传入较大的数据时用作参数
2、传入数组后对数组做操作
3、函数返回值不只一个结果
4、需要用函数来修改不止一个变量
5、动态申请内存

运算符 & *

取地址运算符&:
scanf("%d",&i) ; 里的&
&的作用是获得变量的地址,它的操作数必须是变量

#include
int main()
{
	int i=0;
	printf("%p",&i);//以十六进制形式输出变量i的地址 
	return 0;
}

如果操作数不是变量,例如:a+b、a++、++a之类的就会报错

相邻变量的地址:
例如

#include
int main()
{
	int i=0;
	int j;
	printf("%p\n",&i);//以十六进制形式输出变量i的地址 
	printf("%p",&j);
	return 0;
}

C语言学习笔记——初识指针_第1张图片
我们可以看到地址一个是尾数1C一个是18,在十六进制中8和C相差4,我们知道int类型占4个字节,这代表在内存里,这两个变量是相邻的。再进一步观察,我们可以看到先定义的 i 是
1C,后定义的 j 是18,说明在内存里 i 在更高的地方而 j 在较低的地方。这是因为 i 和 j 都是本地变量,他们分配在内存的堆栈中,在堆栈中分配内存是置顶向下分配的。(后续会学到)

数组的地址:

#include
int main()
{
	int a[10];//定义一个数组 
	printf("%p\n",&a);
	printf("%p\n",a);
	printf("%p\n",&a[0]);//取数组 a  第0个元素的地址 
	printf("%p\n",&a[1]);//取数组 b 第1个元素的地址 
	return 0;
}

C语言学习笔记——初识指针_第2张图片
从输出结果可以看到,前三个地址是一样的,这就说明了直接写取数组名的地址时,默认取的是数组第一个元素的地址,而且可以不用加 & 符号(下文会提及数组与指针的关联)。如若取数组里面某个元素的地址则只需要在 [ ] 中写明取第几号元素即可。据观察可知数组里相邻元素的地址也是相邻的。

间接运算符 * :
指针就是保存地址的变量

#include
int main()
{
	int i=1000;
	int*p = &i;//定义指针类型的变量 p 用来存放变量 i 的地址 
	printf("%d",*p);//*可以理解为取值,*p也就是取指针型变量p所指向的变量地址的值 
	return 0;
}

C语言学习笔记——初识指针_第3张图片
注意:int*p,q 这样定义的话表示定义一个指针型变量 p 和一个整型变量 q

作为参数的指针:

#include
void f(int *p);//定义一个以指针为参数的函数 f 

int main()
{
	int i=1000;
	printf("i =%p\n",&i);//打印 i 的地址 
	f(&i);//调用函数 f 
	return 0;
}

void f(int*p)
{
	printf("p =%p\n",p);//打印 p 的地址 
}

C语言学习笔记——初识指针_第4张图片
敲黑板划重点
我们知道,对函数里的变量进行操作是不会改变主函数中这个变量的值的,但是用指针却可以做到。

#include
void f(int *p);//定义一个以指针为参数的函数 f 

int main()
{
	int i=1000;
	printf("i =%p\n",&i);//打印 i 的地址 
	printf("i=%d\n",i);
	f(&i);//调用函数 f
	printf("i=%d",i); 
	return 0;
}

void f(int*p)
{
	printf("p =%p\n",p);//打印 p 的地址 
	*p=233;
}

还是上一次的代码,这一次在函数中我们把*p赋值为233,然后神奇的事情发生了:
C语言学习笔记——初识指针_第5张图片

i 的值由原来的1000变成了233。原因是使用指针我们从根本上(内存中)改变了变量的值。
实战一下:刚开始学C语言的时候做过的交换两个变量的题

#include
void f(int *pa,int *pb);//定义一个以指针为参数的函数 f 

int main()
{
	int a=1000;
	int b=233;
	f(&a,&b);
	printf("a=%d  b=%d",a,b);
	return 0;
}

void f(int *pa,int *pb)
{
	int tmp=0;
	tmp=*pa;
	*pa=*pb;
	*pb=tmp;
}

在这里插入图片描述

指针应用场景:函数返回多个值

因为函数的返回值只有一个,用指针的话可以带回多个值
例如:找出数组中最大以及最小的数

#include
void minmax(int a[],int len,int *min,int *max);//定义一个以指针为参数的函数 f 

int main()
{
	int min;
	int max;
	int a[10]={1,2,3,4,5,66,78,90,19,28};
	minmax(a,sizeof(a)/sizeof(a[0]),&min,&max);
	printf("min=%d  max=%d",min,max);
	return 0;
}

void minmax(int a[],int len,int *min,int *max)
{
	*min=*max=a[0];
	for(int i=1;i<len;i++)
	{
		if(*min>a[i])
		{
			*min=a[i];
		}
		if(a[i]>*max)
		{
			*max=a[i];
		}
	}
}

C语言学习笔记——初识指针_第6张图片

指针常见错误

定义了指针变量,还没有指向任何变量,就开始使用指针。
必须先要让指针指向某个变量的地址才能用*p对变量的值进行操作。

数组与指针的关联

函数参数表中的数组其实是指针!!!
在参数表中 *ar 等价于ar[ ]

数组变量是特殊的指针
数组变量本身表达地址,所以
int a[10]; int *p=a; //无需用&取地址(虽然用了也不会报错)
但是数组的单元表达是变量,需要用&取地址
例如要取数组a中的3个元素的地址就必须要写成&a[3];

[ ]运算符可以对数组做,也可以对指针做
p[0]==a[0]
例如:

#include
void minmax(int a[],int len,int *min,int *max);//定义一个以指针为参数的函数 f 

int main()
{
	int min;
	int max;
	int a[10]={1,2,3,4,5,66,78,90,19,28};
	minmax(a,sizeof(a)/sizeof(a[0]),&min,&max);
	printf("min=%d  max=%d\n",min,max);
	int *p=&min;//定义一个指针变量p让它指向变量min的地址
	printf("*p=%d\n",*p);//打印指针p所指向的变量min地址存放的值
	printf("p[0]=%d\n",p[0]);//打印数组p[0]的值
	return 0;
}

void minmax(int a[],int len,int *min,int *max)
{
	*min=*max=a[0];
	for(int i=1;i<len;i++)
	{
		if(*min>a[i])
		{
			*min=a[i];
		}
		if(a[i]>*max)
		{
			*max=a[i];
		}
	}
}

C语言学习笔记——初识指针_第7张图片
我们并没有定义数组,它是我们虚构出来的,但是却能编译运行,这说明其实我们把min当作是一个int类型的数组,指针p指向了这个数组。(这一块听得不是太懂…)

今天就先到这了,下回继续。

你可能感兴趣的:(c语言)