1. 指针基础
① 运算符&
“scanf(“%d”,i)”中的&表示获得变量i的地址,它的操作数必须是变量,地址的大小取决于编译器。
&不能对没有地址的东西进行取地址,如&(a+b)、&(a++)都是不可以的。
② 指针
我们要取得地址并用其进行运算,可以用来存储地址的就是指针。
int I;
int* p=&I;
int* p,q;
int *p,q;
上面的语句中p是指针,q是int类型整数,如果p、q都要表示指针,则需要表示为:
int *p,*q;
③ 指针变量
变量的值是内存的地址:普通变量的值是实际的值,指针变量的值是具有实际值的变量的地址。
例1:指针变量
#include<stdio.h>
void f(int *p);
int main()
{
int i=6;
printf("&i=%p\n",&i);
f(&i);
return 0;
}
void f(int *p)
{
printf("p=%p\n",p);
}
运行结果:
6这个数存放在变量i中,变量i的存放地址是&i,将&i传递给指针变量p,p存放的是i的地址。
④ 访问地址上的变量 *
*用于访问指针的值所表示的地址上的变量
printf(“*p=%d”,*p);
会得到p这个指针变量中的地址中存放的变量的结果。
2. 指针的应用
例2:交换两个变量的值
#include<stdio.h>
void swap(int *pa,int *pb);
int main(void)
{
int a=5;
int b=6;
swap(&a,&b);
printf("a=%d,b=%d\n",a,b);
return 0;
}
void swap(int *pa,int *pb)
{
int t=*pa;
*pa=*pb;
*pb=t;
}
在前面的函数部分讲过交换两个数的值的例子,当时是为了讲函数之间传值的问题,我们知道之间用到swap函数是不能完成两个数的值的交换的。为了完成交换,这里我们用到了指针,在swap中对a、b的地址进行交换,从而得到了对其值进行交换的目的。
例3:两个整数相除,如果除法成立返回1,否则返回0
#include<stdio.h>
int divide(int a,int b,int *result);
int main(void)
{
int a=5;
int b=2;
int c;
if(divide(a,b,&c))
{
printf("%d/%d=%d\n",a,b,c);
}
return 0;
}
int divide(int a,int b,int *result)
{
int ret=1;
if(b==0)
ret=0;
else
*result=a/b;
return ret;
}
当我们在对一些运算进行正确与否的判断时,用函数返回运算的状态,结果通过指针返回。
3. 指针常见错误
定义了指针变量,还没有指向任何变量,就开始使用指针。
int i=6;
int k=12;
int *p=12;
这一段语句是错误的,在*p还没有指向任何变量时,就对p指针所指向的地址赋值,因为p指针中还没有地址,有可能会使程序出错。
4. 指针与数组
传入函数的数组实际上是指针,以下四种函数原型是等价的:
int sum(int *ar,int n);
int sum(int *,int);
int sum(int tar[],int n);
int sum(int[],int);
实际上数组变量是特殊的指针,数组变量的本身就表示地址,对数组取地址不需要&,但是对单个单元进行取地址需要使用&。
int a[10];
int *p=a;
int *q=&a[2];
[]运算符可以对数组做,也可以对指针做:
p[0]相当于*p
*运算符可以对指针做,也可以对数组做
*a相当于a[0]
数组变量是const的指针,所以不能被赋值
int a[] 相当于 int *const a=…
5. 指针使用
需要传入较大的数据时用作参数;
传入数组后对数组做操作;
函数返回不止一个结果;
需要用函数来修改不止一个变量(如swap);
动态申请内存。