1 指针是什么
指针是C语言的特色之一,利用它可以写出高效率的程序。在介绍指针之前,先来统一对内存的认识。
内存可看成是由许多字节顺序排列而成,每个字节都有唯一的内存地址。
对于每个变量,C系统会根据变量的类型,在内存中分配相应大小的存储单元,用于存放变量的值。
人们把变量所对应的存储单元的首字节的地址称为变量的地址,可用取地址运算符&来获取变量的地址。
由于变量的地址指明了变量的存储位置,所以被说成是“指向”变量,并形象地称为变量的指针
2 指针变量
可以定义变量来存放变量的地址/指针,这种用来存放地址的变量称为指针变量。指针变量可按如下形式定义:
基类型 *指针变量名1,…,*指针变量名m;
基类型有以下两方面的作用:
1.基类型规定了指针变量中可存放哪类变量的地址
2.指针变量参与运算时,计算结果依赖于基类型。
与其他变量一样,在定义指针变量时可为它设置初值。 int i=5,*p=&i;
由于指针变量p中存放了变量i的地址,于是就在这两个变量之间建立了联系,人们把这种联系称为:
p是指向变量i的指针变量
或称 p指向变量i
⑴ 取地址运算符&的一般形式为:
&变量
⑵ 指针运算符*的一般形式为:
*Addr
它用来获取变量的地址,可将该地址赋值给同类型的指针变量。
3 通过指针引用数组
与其他变量一样,指针变量也可以作为函数参数。具体地说,指针变量既可作为形参,也可作为实参。
不仅如此,在调用时,也会把实参指针变量p的值传递给对应的形参指针变量q。
void f2(int* q, int c)
{
*q=(*q) * 10;
c=c+2;
}
int main()
{ int a=3,b=5;
int *p;
p=&a;
f2(p, b);
printf(“%d %d”,a,b);
return 0;
}
4 通过指针引用字符串
对于字符串常量如”CHINA”,系统会为它分配一组地址连续的存储单元,最后一个单元用于存放字符串结束符。
不难看出,字符串中每个字符均有自己的存储单元和地址。
可以定义
char* p, *q;
使它指向串中的某个字符。
若想使得q指向数组a中的字符串USA,只需执行以下语句即可。
q=a;
或者 q=&a[0];
另外,当q指向字符串后,q+i指向串的第i个字符,
*(q+i), q[i], *(a+i), a[i]
均表示串的第i个字符。
进一步地,当q指向字符串后,
q++;
或 ++q;
可使q指向串的下一字符。
若想使得p指向字符串常量”CHINA”,只需执行以下语句即可。
p=”CHINA”;
5 指向函数的指针
如果在程序中定义了若干个函数,在编译时,编译系统会为每个函数的代码分配一段存储区域,每个函数所对应的存储区域的起始地址,称为该函数的入口地址或指针。
可以定义一个指针变量p,用来存放函数max的指针。
int(*p) max(int x,int y);
p=max;
printf(“%d”,(*p)(3,5));
如何把函数max的指针存放到p中呢?
由于函数名max就表示其入口地址,因此可用上述赋值语句完成任务。
此时,p指向函数max。*p表示max,于是,
(*p)(3,5)
等价于 max(3,5)
6 返回指针值的函数
许多函数有返回值,返回值不仅可以是整型数据、实型数据,而且可以是某种类型数据的指针,这种函数称为指针函数。因此,指针函数返回的是某个数据对象的地址。
类型* 函数名(形参列表)
{
…
}
7 二级指针
int** q;
q=&p;
8 动态内存分配与指向它的指针变量
到目前为止,我们编写的含有排序功能的程序都是如下 组织的。
有时,我们需要保存某一内存区域的起始地址,但并不知道该区域所存放的数据的类型,这时可以如下定义void类型的指针变量。
void* 指针变量; void* p;
malloc函数:
函数原型: void* malloc(unsigned int n);
功能:在内存中分配一个n字节的存储空间,并返回其首字节的地址。由于malloc并不知道或者不关心这片内存的用途,所以首地址是以void类型的指针返回的。
free函数:
函数原型: void free(void *p);
功能:释放动态分配的空间,p为malloc的返回值。