孙道层
(德宏职业学院 云南省芒市 678400)
C语言程序中涉及的数据都存放在计算机内存中,计算机内存按照编号进行寻址,根据这个编号访问相应的内存数据,这个编号就是访问内存数据的地址,这个编号或者地址就是指针[1-2]。
指针变量是指存储的地址可以变化的变量,在计算机内部存储中,在计算机内存中,同种类型的数据往往存储在一块连续的内存区域,地址是常量,不能变化移动地访问连续的内存单元,指针变量通过指针的移动指向连续存储区域的不同单元,表达方便明确,概念更加清晰,因此在C语言程序设计中得到广泛的应用[3-4]。
广义上来理解,C语言中只要对象有地址,都可以通过指针变量关联这个对象,例如指针变量关联字符串常量、普通基本类型变量、结构体类型变量,还可以关联数组、函数、文件等对象,贯彻C语言程序设计各个章节知识点,也在程序设计中发挥重要的作用,指针变量正确的使用能够提高C语言程序代码可读性,提高程序的运行效率,不恰当的使用会导致代码可读性差,影响编译执行效率[5]。本文通过指针变量的概念界定、指针变量关联对象的引用及注意事项,深入分析各类指针变量内涵和使用场合,对学习者如何快捷系统全面学习指针变量具有借鉴意义,对从事面向过程C语言程序设计开发者如何正确有效使用各类指针变量提高程序代码质量具有实践借鉴意义。
一级指针变量对普通基本类型变量的关联引用形式:*指针变量名;“*”表示该变量是指向普通基本类型变量的一级指针变量。关联基本类型变量的二级指针变量定义形式:基本类型变量说明符**指针变量名,“**”有两层含义,一方面表示该变量名属于二级指针变量,另一方面表示该指针变量指向的对象是基本类型变量。
例1 指针变量关联引用基本类型变量
#include “stdio.h”
void main()
{ int c=5,*p1=&c,**p2=&p1;
printf(“c=d% *p1=d% **p2=d% ”,c,*p1,**p2);
}
其中p1为一级指针变量,c前面关键字是int表示c为整型变量,把变量c的内存地址赋值给指针变量p1,p1根据存放的地址指向整型变量c,*p1与c的值是同一对象,p1=&c,*p1=c;p2是二级指针变量,指向指针的指针,p2的内容是一级指针变量p1的地址,*p2是指向指针变量p1,**p2是指向整型变量c,p2=&p1,*p2=p1,**p2=c。关系如图1所示。
图1:指针变量对整型变量的引用
在C语言中字符串没有变量,只有常量,可以通过指针变量关联指向字符串常量,指针变量的移动来访问移动后的指针变量指向的字符元素,指针变量关联字符串的定义形式:
字符类型标识符* 字符串指针变量名;
例2指针变量关联引用字符串
#include “stdio.h”
void main()
{ char *p= “string”;
puts(p+3);
}
p是字符指针变量,并将字符串常量”string”首个元素地址赋值给p,p+3表示从首个元素开始向后推移三个元素移动后的地址,即指向‘i’这个元素,输出的结果是“ing”。关系如图2所示。
图2:指针变量对字符串常量的引用
一维数组是由一个下标从零开始排列的同类型变量组成结构单一的集合,一维数组在计算机内部存储空间是一片连续的区域,把这片连续区域的首地址赋值给指针变量,就可以通过指针变量引用一维数组元素。一维数组指针变量的定义一般形式:
一维数组类型说明符*指针变量名;
指针变量关联引用一维数组元素一般形式:
*(指针变量+表达式),表达式一般是算术表达式,在一维数组就是指元素的所在连续单元的标号。
例3 指针变量关联引用一维数组元素
#include “stdio.h”
void main()
{ inti,a[6]={1,2,3,4,5,6};
Int *p=a;
for(i=0;i<6;i++)
printf(“%d ”,*(p+i));
printf(“ ”);
}
定义一个指针并把数组名a赋值指针变量p,指针变量p指向数组首个元素a[0],*(p+i)表示一维数组第i个元素,也可以表示为p[i],通过for循环语句执行6次,分别输出数组元素的值。如图3所示。
图3:使用指针变量指向一维数组
二位数组由一维数组嵌套构成的,可以将每一行看成一个一维数组,若有定义:int c[2][3],把c当成由c[0]和c[1]两个元素组成一维数组,c[0]和c[1]里面的元素分别又组成一个一维数组。如图4所示。
图4:使用指针指向二维数组
二维数组指针变量对二维数组元素的关联引用形式:*(*(指针变量名+行表达式)+列表达式);
例4指针变量对二维数组的关联引用
#include “stdio.h”
void main()
{ intm,n,c[2][3]={1,2,3,4,5,6};
int **q=c;
for(m=0;m<2;m++)
for(n=0;n<3;n++)
printf(“%d”,*(*(q+m)+n));
printf(“ ”);
}
*(q+m)+n表示c[m][n]元素的地址即&c[m][n],*(*(q+m)+n)表示前面相应地址所指向的元素即c[m][n]。
定义函数就需要计算机内部存储区域分配相应的存储空间给函数,并把这个已经分配的存储空间的地址赋值指针变量,该指针变量就指向已经定义的函数,把某一个函数的入口地址赋值给指针变量,该指针变量就可以对指向的函数进行调用,
函数指针变量关联引用函数的一般形式:(*指针变量名)(实参表);
例5指针变量对函数的关联引用
#include “stdio.h”
int min(int,int);
void main()
{ int (*p) (int,int);
inta,b;
int m;
scanf(“%d,%d”,&a,&b);
p=min;
m=(*p) (a,b);
printf(“m=%d ”,m);
}
int min (intc,int d)
{ int n;
n=(c<=d)? c:d;
return (n);
}
结构体变量定义之后,在计算机内存中会分配一块连续的存储区用来存储结构体变量里的各个成员数据,这块连续存储首地址就是单元首个元素的地址,也是该结构体变量的地址,把这块连续的存储区域地址赋值给指针变量,指针变量就可以调用此结构体变量成员。
声明结构体类型指针变量的形式:struct结构体类型名* 结构体指针变量名;
结构体指针变量关联引用结构体变量形式:指针变量名->成员名或(*指针变量名).成员名;
例6结构体指针变量关联引用结构体变量
#include <stdio.h>
struct student
{ longstudent_num;
charstudent_name[10];
charstudent_sex;
intstudent_age;
};
Void main()
{ structstudent stu = {“20131104”,“zhangsan”,‘男’,20},*p=&stu;
printf(“student_name:%s,student_age:%d ”,
(*p).student_name,p->student_age);
}
例6中,把结构体变量stu的地址赋值给指针变量p,可以用指针变量p引用变量stu的成员,此时(*p).student_name表示引用结构体变量stu的name成员,p->student_age表示引用结构体变量stu的age成员。
通过文件指针将数据流与特定的文件进行关联,文件指针是一个FILE类型的文件结构体指针变量,指针变量可以实现对已经打开的文件进行读写操作,指针变量关联文件的定义形式:FILE * 指针变量标识符;
其中FILE必须大写,指针变量标识符可以自行定义,满足C语言标识符的命名规则即可,比如:FILE *fp;“*”表示该变量fp是一个指针变量,FILE表示fp是指向文件的指针变量,通过文件指针变量fp可以对已经打开的指定文件进行相应的操作。也就是通过将文件的FILE结构体变量地址赋值给文件指针fp,则在程序中就建立了文件和文件指针间的联系,程序就能通过该文件指针找到与它相关的文件,实现对文件的操作,在C语言中,凡是要对已打开的文件进行操作,都要通过指向该文件的文件指针实现。
例8 指针变量关联引用文件
#include <stdio.h>
void main()
{ charch;
FILE * fp;
fp = fopen(“E:/CFile/test.txt”, “r”);
ch = fgetc(fp);
while(ch!=EOF)
{ putchar(ch);
ch=fgetc(fp);
}
Fclose(fp);
}
文件指针变量fp指向一个已打开的文件“test.txt”,用fgetc(fp)字符读函数从文件指针fp指向的文件读取字符并赋值给字符变量ch,并通过while循环体语句继续读写fp所指向的文件字符,文件读取操作完成后,使用fclose函数关闭fp所指向的文件。
在C语言中只有指针变量可以存放某类数据的地址,这类数据可以是普通变量、字符串、数组、函数、结构体变量、文件等数据类型。不同类型的指针变量存储的值都是不同类型数据对象在计算机内存中的地址,C语言指针变量是依据它所指向的变量对象类型不同进行区分,不同类型的指针变量是不能进行赋值运算。
C语言的精髓是指针,指针变量的正确使用能够提高C语言程序代码的可读性,提高程序的运行效率,错误的使用指针变量会导致程序出错或者是运行效率低下,通过系统研究指针变量对其它对象的关联引用,有利于学习者和开发者使用各类指针变量提高C语言程序设计代码质量。