程序中定义的变量,在编译时,系统会给这个变量分配内存单元,根据数据类型,分配一定的长度空间。如Visual C++为整型变量分配4个字节,float分配4个字节,对char分配1个字节,内存区的每个字节有一个编号,这就是“地址”。由于通过地址能找到所需的变量单元,可以说,地址指向该变量单元,将地址形象的称为”指针”,即一个变量的地址称为该变量的”指针”。
指针变量,也是地址变量; 如:
int i=3; / 定义整型变量并初始化
int *i_pointer; / 定义整型数据的指针变量
i_pointer=&i; / 将i 的地址存放到i_pointer中,比如变量i 所占用单元的起始地址为2000,那么i_pointer=2000 。
*i_pointer=3; 其中*i_pointer 表示指向的对象,指向就是通过地址来实现的。通过i_pointer=2000的地址指向该变量单元,即 i 的值为3.。 例中变量i 的指针为2000(地址),指针变量i_pointer 只是存放地址的变量,不能说i的指针变量是2000。
定义指针变量:
类型名 *指针变量名; 如:int *pointer_1; 对它初始化还可以写成int *pointer_1=&a ;
上面定义的指针变量前面的" * " 表示该变量的类型为指针类型,在定义指针变量时必须指定基类型,因不同类型的数据在内存中所占的字节数和存放方式是不同的。指针变量只能存放地址(指针),不能将一个整数赋给一个指针变量,如*i_pointer=100; 把整数100赋给指针变量是非法的。合法赋值为 i_pointer=&a;
数组指针:
数组元素的指针就是数组元素的地址。如;
int a[10]={1,2,3,4,5,6,7,8,9,10};
int *p; / 定义指针变量
p=&a[0]; 或 p=a; / 把a[0]即数组首元素的地址赋给p 。
数组名a代表数组中首元素a[0]的地址,而不是代表整个数组。
当指针指向数组元素的时候可以对指针进行加减运算,执行p+1时并不是将p的值 (地址)简单的加1,而是加上一个数组元素所占用的字节数。如int 占4个字节,p的值(地址)为2000时,则p+1的值是2004,指向的是数组的下一个元素如a[1]; *(p+1)为a[1]的值。
*p++等价于*(p++) , *(p++)为先取*p的值,然后再使p+1;而*(++p)为先使p+1,再取*p的值,如p初值为a(即&a[0]),若输出*(p++),得到a[0]的值,若输出*(++p),则得到a[1]的值;++(*p)表示p所指向的元素值加1,不是指针p加1。
二维数组指针:
可以认为二维数组是“数组的数组”,如 int a[3][4]; ,a代表二维数组首地址,a+1代表序号为1的行的首地址,即指向a[[1],为a[1]的首地址。比如a即二维数组的首地址为2000,a+1的地址为2000+4x4=2016(因为0行有4个整型数据),a+2代表a[2]的首地址为2032.
在二维数组中,a[0]是一维数组名,所以 a[0]+1 代表的是二维数组0行1列元素的地址,即地址为2000+4(而不是2016),相当在一维数组范围内讨论。因为a[0] 和 *(a+0)等价,即 a[ i ] 和 *(a+i) 等价, 所以a[0]+1 和 *(a+0)+1都是&a[0][1](即地址的值为2004), 若想得到a[0][1]的值可表示为 : a[0][1] 或 *(a[ 0 ] +1) 或 *(*(a+0)+1) 或 *(*a+1)
通过以下例子理解:
输出二维数组的有关数据(地址和值)
int main()
{
int a[3][4]={1,3,5,7,9,11,13,15,17,19,21,23};
printf("%d,%d\n", a,*a); / 0行首地址 和 0行0列元素地址
printf("%d,%d\n", a[0], *(a+0)); / 0行0列元素地址
printf("%d,%d\n", &a[0], &a[0][0]); / 0行首地址 和 0行0列元素地址
printf("%d,%d\n", a[1],a+1); / 1行0列元素地址 和 1行首地址
printf("%d,%d\n", &a[1][0],*(a+1)+0); / 1行0列元素地址
printf("%d,%d\n", a[2],*(a+2)); / 2行0列元素 地址
printf("%d,%d\n", &a[2],a+2); / 2行首 地址
printf("%d,%d\n", a[1][0],*(*(a+1)+0)); / 1行0列 元素的 值
printf("%d,%d\n", *a[2],*(*(a+2)+0)); / 2行0列 元素的 值
return 0;
}
运行结果:
1245008,1245008
1245008,1245008
1245008,1245008
1245024,1245024
1245024,1245024
1245040,1245040
1245040,1245040
9,9
17,17
以上程序运行结果,不同编译环境,由于分配的内存不一样,所显示的地址可能不同,但是都是有共同规律的。
字符串指针引用:
用字符指针变量指向一个字符串常量,通过字符指针变量引用字符串常量。在字符串中 ,虽然未定义字符数组,但字符串在内存中是以字符数组形式存放的,a[ i ] 和 *(a+i) 也是等价的。
如;
char *string="I love china!";
等价于:
char *string; / 定义一个char型变量
string="I love china!"; / 把字符串第一个元素的地址赋给字符指针变量string,不能写成*string
再例:将字符串a复制为字符串b,然后输出字符串b
int main()
{
char a[]="I am a boy.",b[20],*p1,*p2;
p1=a;p2=b; / p1,p2分别指向a数组和b数组中的第一个元素
for(;*p1!='\0';p1++,p2++) / p1,p2每次自加1,其中'\0'也可以用ASCII代码 0 来代替
*p2=*p1; / 将p1所指向的元素的值赋给p2所指向的元素
*p2='\0'; / 在复制完全部有效字符后加'\0'
printf("string a is:%s\n",a); / 输出a 数组中的字符
printf("string b is:%s\n",b); / 输出b 数组中的字符
return 0;
}
运行结果:
string a is:I am a boy.
string b is:I am a boy.
函数指针:
在编译时,编译系统会为函数代码分配一段存储空间,这段存储空间的起始地址称为这个函数的指针。如:
类型名 ( *指针变量名 ) ( 函数参数表列 ) → int (*p) ( int , int);
定义p是一个指向函数的指针变量,它可以指向函数的类型为整型且有两个整型参数的函数。注意:*p两侧的()不可省略,表示p先与*结合,是指针变量,然后再与后面的()结合,()表示函数,即该指针变量不是指向一般的变量,而是指向函数。
用指针调用函数:
如给函数指针变量赋值:p= max; // 将函数入口地址赋给p ,不能写成p=max(a,b); ,只需给出函数名不需给出参数。
用函数指针变量调用函数:如: c=(*p)(a,b); // 调用由p指向的函数,实参为a,b ,得到的函数值(函数返回的类型值)赋给c。
用指向函数的指针作函数参数:例:
主要方便用于多次调用不同函数:
#include<stdio.h>
int main()
{
int fun(int x,int y,int (*p)(int,int)); / fun 函数声明
int max(int,int); / max 函数声明
int min(int,int); / min函数声明
int add(int,int); / add函数声明
int a=34,b=-21,n
printf("please choose 1,2 or 3:");
scanf("%d",&n); / 输入1,2,或 3之一
if(n==1) fun(a,b,max); / 输入1 时调用 max函数
else if(n==2) fun(a,b,min); / 输入2 时调用 min函数
else if(n==3) fun(a,b,add); / 输入3 时调用 add函数
return 0;
}
int fun(int x,int y,int(*p)(int,int)) / 定义fun函数
{
int result;
result=(*p)(x,y);
printf("%d\n",result);
}
int min(int x,int y) / 定义min 函数
{
int z;
..
return (z);
}
int max(int x,int y) / 定义max 函数
{
int z;
..
return (z);
}
int add(int x,int y) / 定义add 函数
{
int z;
..
return (z);
}
指针小结
变量定义 | 类型表示 | 含义 |
---|---|---|
int i; | int | 定义整型变量i |
int *p; | int * | 定义p为指向整型数据的指针变量 |
int a[5]; | int [5] | 定义整型数组a,它有5个元素 |
int *p[4]; | int *[4] | 定义指针数组p,它由4个指向整型数据的指针元素组成 |
int (*p)[4]; | int (*)[4] | p为指向包含4个元素的一维数组的指针变量 |
int f(); | int () | f为返回整型函数值的函数 |
int *p(); | int *() | p为返回一个指针的函数,该指针指向整型数据 |
int (*p)(); | int (*)() | p为指向函数的指针,该函数返回一个整型值 |
int **p | int ** | p是一个指针变量,它指向一个整型数据的指针变量 |
void *p; | void * | p是一个指针变量,基类型为void(空类型),不指向具体的对象 |
指针运算:
例:p++ ,p- - , p+i ,p-i , p+=i , p- = i . 将该指针变量的原值(是一个地址)和它指向的变量所占用的存储单元的字节相加减。
指针赋值:
例:
p = &a ; (将变量a的地址赋给p)
p = array ; (将数组array首元素地址赋给p)
p = &array[i] ; (将数组array第i个元素的地址赋给p)
p = max ; (max 为已定义的函数,将max的入口地址赋给p)
p1 = p2 ; (p1和p2是基类型相同指针变量,将p2的值赋给p1)
注意:不应把一个整数赋给指针变量
p = NULL ; NULL是一个符号常量,在stdio.h 头文件定义 #include NULL 0