指针变量的定义
例:
Int *p /*int是类型说明符号;”*”是指针类型说明符;p是变量名*/
注意:区别指针取内容运算符”*”和指针变量说明中的指针说明符”*”。在指针变量说明中,”*”是类型说明符,表示其后的变量是指针类型。而表达式中出现的”*”则是一个运算符,用以表示指针变量所指的变量。
指针变量的赋值
- 指针变量初始化的方法。
例如:
int a; //预先定义说明变量
int *p=&a;
- 把一个变量的地址赋予指向相同数据类型的指针变量。
例如:
int a,*p;p=&a; //把整型变量a的地址赋予整型指针变量p。
- 把一个指针变量的赋值予指向相同类型变量的另一个指针变量。
例如:
int a,*q=&a,*p;p=q; //把指针变量q的值(变量a的地址)赋予指针变量p。
注意:
- 只有指向相同类型变量的指针变量才可以相互赋值。
- 不允许把一个数赋予指针变量,故下面的赋值是错误的:
int *p;p=1000;
被赋值的指针变量前不能再加”*”说明符,如写为*p=&a也是错误的。
编程实现定义两个指向整型变量的指针变量p1、p2,若p1指向的变量的值小于p2指向的变量的值,则变换p1和p2
程序代码如下:
#include<stdio.h>
int main()
{
int a,b;
int *p1=&a,*p2=&b,*t;
scanf("%d%d",&a,&b);
if(*p1<*p2)
{
t=p1;
p1=p2;
p2=t;
}
printf("%d,%d\n",*p1,*p2);
printf("%d,%d",a,b);
return 0;
}
输入:1 2
运行结果:
2,1
1,2
--------------------------------
Process exited after 3.154 seconds with return value 0
请按任意键继续. . .
将程序代码改成如下:#include<stdio.h>
int main()
{
int a,b,t;
int *p1=&a,*p2=&b;
scanf("%d%d",&a,&b);
if(*p1<*p2)
{
t=*p1;
*p1=*p2;
*p2=t;
}
printf("%d,%d\n",*p1,*p2);
printf("%d,%d",a,b);
return 0;
}
输入:1 2
运行结果如下:
2,1
2,1
--------------------------------
Process exited after 2.205 seconds with return value 0
请按任意键继续. . .
注意:第一段代码中交换的是p1和p2的值,即p1指向了b,p2指向了a,所以,没有交换a、b的值。第二段代码中交换的是*p1和*p2的值,@即交换了a和b的值。
输入两个整数并按大小顺序是出其值。要求用函数处理,并且用指针类型的数据作函数的参数。
程序代码如下:
#include<stdio.h>
int main()
{
int a,b;
int *pointer_1,*pointer_2;
scanf("%d%d",&a,&b);
pointer_1=&a;
pointer_2=&b;
if(a<b)
swap(pointer_1,pointer_2);
printf("%d %d\n",a,b);
return 0;
}
int swap(int *p1,int *p2)
{
int temp;
temp=*p1;
*p1=*p2;
*p2=temp;
}
注意:如果swap()函数写成以下这样就有问题了。
int swap(int *p1,int *p2)
{
int *temp;
*temp=*p1;
*p1=*p2;
*p2=*temp;
}
*p1就是变量a,是整型变量,而temp被定义为指针变量,*temp则是指针变量temp所指向的变量。由于temp未赋值,所以temp所指向的单元是不可预见的。因此对*temp赋值就是向一个未知的单元赋值,有可能破环系统的正常工作。
对比本例的swap2()函数与上一例中的swap()函数的不同。
程序代码如下:
#include<stdio.h>
int main()
{
int a,b;
int *pointer_1,*pointer_2;
scanf("%d%d",&a,&b);
pointer_1=&a;
pointer_2=&b;
if(a<b)
swap2(pointer_1,pointer_2);
printf("%d %d\n",a,b);
return 0;
}
int swap2(int *p1,int *p2)
{
int *temp;
temp=p1;
p1=p2;
p2=temp;
}
注意:指针变量作实参时,与普通变量一样,也是值传递,即将指针变量的值(一个地址)传递给被调用函数的形参(必须是一个指针变量)。被调用函数不能改变实参指针变量的值,但可以改变实参指针变量所指向的变量的值。
指向数组的指针变量的运算
(1)赋值运算
例如:
int a[5]; //定义a为包含5个整型数据的数组
int *p; //定义为指向整型变量的指针
P=a; //把数组a的首地址赋给指针变量p
P=&a[0];//把a[0]元素的地址赋给指针变量p,即p指向数组a的第0号元素
注意:因为数组为int型,所以指针变量也应为指向int型的指针变量。
c语言规定,数组名代表数组的首地址,也就是第0号元素的地址。因此,下面两个语句等价:
p=&a[0];
p=a;
在定义指针变量时可以赋给初值:
int *p=&a[0];
它等效于:
int *p;p=&a[0];
当然定义时也可以写成:
int *p=a;
(2)加减算术运算
例如:
int a[3],*p;
p=a;//p指向数组a,也是指向a[0]
p=p+1;//p指向a[1],即p的值为& a[1]
注意:指针变量的加减运算只能对数组指针变量进行,对指向其他类型变量的指针变量作加减运算是毫无意义的。
(3)两个指针变量之间的运算
(只有指向同一数组的两个指针变量之间才能进行运算,否则运算毫无意义。)
a.两指针变量相减
例:p1和p2是指向同一浮点数组的两个指针变量,设p1的值为2012H,p2的值为2000H,而浮点数组每个元素占4字节,所以p1-pa的结果为(2012H-2000H)/4=3,表示pf1和pf2之间相差3个元素。
注意:两个指针变量不能进行加法运算。例如,pf1+pf2毫无意义。
输出数组a中的全部元素。
下标法:
#include<stdio.h>
int main()
{
int a[6],i;
for(i=0;i<6;i++)
a[i]=i;
for(i=0;i<6;i++)
printf("%d ",a[i]);
return 0;
}
通过数组名计算元素的地址,找出元素的值:
指针法:
注意:指针变量可以实现本身的值的改变。例如,p++是合法的,而a++是错误的。因为a是数组名,即数组的首地址,是常量。
字符指针的定义
字符指针法表示字符串是直接定义一个字符类型的指针变量并指向字符串首地址。
例如:
char *s=”TURBO C”;//表示s是一个指向字符串的指针变量。把字符串的首地址赋予s
注意:初始化时应写出整个字符串常量,以便编译系统把该串装入连续的一块内存单元,并把首地址赋给指针变量。C语言对字符串常量是按字符串数组处理的,在内存中开辟了一个字符数组存放字符串常量,但是该数组没有名字,不能用数组名来引用,只能用指针变量引用。
把一个字符串的内容复制到另一个字符串中。
程序代码如下:
#include<stdio.h>
int main()
{
char *pa="CHINA",b[10],*pb;
pb=b;
spystr(pa,pb);
printf("%s",pb);
return 0;
}
int spystr(char *p1,char *p2)
{
while(*p2++=*p1++);
}
注意:该程序中形参和实参都是字符指针变量。
定义方式不同。
定义一个字符数组要符合数组定义的语法,而定义一个字符指针要符合指针变量定义的语法。
例如:
char str1[ ]=“c program”;
char str2[ ]=”c prongraam”;
注意:二者的初始化含义不同。字符指针变量str2的初始化实际是赋予了字符串常量的第一个字符的储存地址,而不是整个字符串。
用函数指针变量调用函数,比较两个数的大小。
程序代码如下:
#include<stdio.h>
int main()
{
int max(int x,int y);
int (*p)(int,int);
int a,b,c;
p=max;
scanf("%d%d",&a,&b);
c=(*p)(a,b);
printf("a=%d,b=%d,max=%d\n",a,b,c);
return 0;
}
int max(int x,int y)
{
int z;
if(x>y)
z=x;
else
z=y;
return z;
}
注意:函数指针变量不能进行算术运算,这是与数组指针变量不同的。数组指针变量加减一个整数可以使指针移动指向后面或前面的数组元素,而函数指针的移动是毫无意义的。
函数调用中(*指针的变量名)两边的括号不可少,其中的“*”不应该理解为求值运算,在此处它只是一种表示符号
应该特别注意的是指针变量和指针型函数这两者在写法和意义是的区别,如int(*p)()和int *p()是两个完全不同的量。int(*p)()是一个变量说明,说明p是一个指向函数入口的指针变量,该函数的返回值是整型量,(*p)两边的括号不能少。int*p()则不是变量说明而是函数说明,说明p是一个指针型函数,其返回值是一个指向整型量的指针,*p两边没有括号。作为函数说明,在括号内最好写入形式参数,这样便于变量说明区别。
对于指针型函数定义,int *p()只是函数头部分,一般还应该有函数体部分。
比较指针数组和一维数组指针的区别。
程序如下:
#include<stdio.h>
int main()
{
int a[3][3]={1,2,3,4,5,6,7,8,9};
int *pa[3]={a[0],a[1],a[2]};
int *p=a[0];
int i;
for(i=0;i<3;i++)
printf("%d,%d,%d\n",*pa[i],p[i],*(p+i));
return 0;
}
运行结果:
1,1,1
4,2,2
7,3,3
--------------------------------
Process exited after 0.2872 seconds with return value 0
请按任意键继续. . .
注意:指针数组和一维数组指针变量的区别。一维数组指针变量是单个的变量,其一般形式中(*指针变量名)两边的括号不可少。而指针数组类型表示的是多个指针(一组有序的指针),在一般形式中*指针数组名两边不能有括号。
例如:
int (*p)[5];//表示一个指向二维数组的指针变量。该二维数组的数列为5
int *p[5];//表示p是一个指针数组,有5个下标变量:p[0],p[1],p[2],p[3],p[4],均为指针变量
指针数组也常用来表示一组字符串。指针数组的每个元素被赋予一个字符串的首地址。指向字符串的指针数组的初始化更为简单。例如char *cn={“basic”,”turboc,””java”};,即cn[0]指向字符串basic,cn[1]指向turboc,cn[2]指向java。
指针数组还可以用作函数参数。