C语言指针应用

2024-06-01

C语言指针应用(共10篇)

C语言指针应用 篇1

“指针”是C语言中广泛使用的一种数据类型 , 运用指针编程是C语言最主要的风格之一。利用指针可以表示各种数据结构, 它与函数、数组的使用和传递数据有密切联系, 能方便地访问数组, 还能像汇编语言一样处理内存地址, 从而编出精致而高效的程序。指针极大地强化了C语言的功能。学习指针是学习C语言最重要的一环, 能否正确理解和使用指针是判断是否掌握了C语言的重要标志。但是指针也是C语言最危险的特性, 如果使用不当, 则很容易指到意想不到的地方, 产生错误也很难发现。因此, 对于初学者来说, 应特别注意指针的应用。怎样才能应用好指针呢?下面笔者以在计算机C语言教学中的体会与大家进行探讨。

一、理解指针

在C语言中任何数据只要定义了, 在内存中就是有一定的存储单元的。存储单元就是变量在计算机中的存储地址, 指针就是用来表示这些地址的变量。所以简单地说, 指针就是地址, 变量的指针就是变量的地址, 这里还涉及一个概念就是指针变量, 所谓指针变量就是用来存放指针 (地址) 的变量。例如:int a;假设a的地址是2000, 而2000又存储在变量point中, 那么变量point就是指针的变量简称指针变量, a就是指针变量所指向的变量。很多初学者都存在这样的误区:既然指针放的是地址, 而2000正好是变量a的地址, 那么对于指针point就可以这样赋值:point=2000, 这是错误的, 这里的2000表示的不是地址是一个整型数据。所以对于指针变量的赋值只能用取地址运算符“&”进行赋值即:point=&a;&a即为a的地址。

二、指针与函数

指针作为C语言的精华有很多用途, 除具有一般的功能外, 其中具体特殊功能的应用总结起来有三个方面:一是用于在函数中可以返回多个值;二是可以实现动态调用函数;三是实现数组的动态定义。其中, 普通变量作为函数的参数, 传递的是变量的值, 因此只能带回一个返回值, 但在有些场合需要返回多个值, 这就必须用到指针做函数的参数, 因为指针作为参数传递的是地址, 让实参和形参指向同一个变量的地址, N个形参所指向的变量的值改变了, N个实参的值也自然改变了, 从而实现了带回多个返回值。这里举个例子, 编写一个函数实现两个数从小到大输出。这个程序需要子函数实现两个数的交换, 把交换后的两个值通过指针传回主函数输出, 传回来的是两个值。所以普通变量做函数的参数是无法实现的, 只能用指针作为函数的参数。具体实现:

子函数实现交换:

由此可见, 要通过函数调用得到N个返回值可以通过以下三步实现: (1) 主调函数中设N个变量, 用N个指针指向他们; (2) 将指针变量作实参 , 将N个变量的地址传给形参 ; (3) 通过形参指针变量指向的改变, 改变N个变量的值。最后主调函数中就可以得到N个变量的返回值。

三、指针与数组

前面提到任何数据都有存储单元, 都有指针。所以, 从这个角度出发可以将指针分为:指向变量的指针、数组指针、字符指针、指向指针的指针、函数指针、结构变量的指针及文件指针, 等等。其中, 指向变量的指针就是存储变量的地址的, 这是指针最简单的一种类型。那么一个变量有地址, 一个数组有若干个元素, 每个元素都有一个地址, 所谓数组的指针, 就是指数组的名称, 实际上是指向整个数组空间的起始地址。数组元素的指针是数组元素的地址。例如:int a[10];int*p;这里的数组名a就是数组的首地址, 本质上是一个指针。a[2]表示距离a指向空间向后2个位置所在空间中的存放的值, 所以a[2]=* (a+2) 。那么如果让p=a, p就是指向数组的指针 , 对于a我们可以做加减整数运算, 利用它表示数组中任何数据的值。那么对于指针也可以通过加减整数运算来表示数组中的任何数据。指针变量加上或减区一个整数n表示把指针指向的当前位置向前或向后移动n个位置。具体移动的字节数和指针数组的类型在内存所占的字节数有关系, 如果指针数组类型为整型, 在内存中占2个字节, 那么, 指针p+1, 实际上的地址值就是原址加2, 对于数组元素来说就是指针向后移动一个元素。如int a[10], *p, *s;p=a;s=p+2;其中s的值表示数组中首地址向后移动2个数组元素的位置 , 表示a[2]对应的地址 , 而具体移动的字节数则为4个字节。为了表示两个地址间存在的距离, 可以通过指针间的减法实现。指针之间是不能有加法操作的, 指针的加减运算只能对数组指针变量进行, 对指向其他类型的变量的指针变量做加减运算是毫无意义的。而且两个指针变量之间的运算只有指向同一数组时它们之间才能进行运算, 否则运算将失去意义。

四、结语

C语言是到目前为止学习最多的程序设计语言之一 , 也是国外大学计算机专业唯一的必修课程。在整个C语言教学中, 指针是一个十分重要的部分, 也是最难掌握的部分之一。本文从对指针概念的理解、指针在函数和数组的使用等方面系统论述了指针, 目的是让大家清晰地了解指针、掌握指针, 从而高效地应用指针。只有掌握好指针, 才能充分发挥C语言的优势。

摘要:“指针”是C语言的精髓, 是C语言区独有的功能, 在C语言的程序设计过程中起着不可或缺的作用。只有学好了指针才算掌握了C语言, 同时指针也是C语言最危险的特性, 如果使用不当, 则很容易指到意想不到的地方, 产生错误很难发现。应该特别注意指针教学, 高效应用指针, 发挥C语言的优势。

关键词:C语言,指针,函数,数组

参考文献

[1]谭浩强.C程序设计教程.北京:清华大学出版社, 2008, 11.

[2]陈刚.C语言程序设计.清华大学出版社, 2010, 2.

[3]魏海新, 李燕.C语言程序设计实用教程.机械工业出版社, 2007, 7.

[4]路俊维, 马雪松.C语言程序设计.中国铁道工业出版社, 2009, 6.

C语言指针应用 篇2

一、实习目的

姓名:尹思智

学号:2012014413

完成日期:2013年4月

1.由键盘输入10个整数,将它们从小到大排序 2.将10个字符串(设其长度小于30)排序。

3.找出二维数组(设4行5列)中的最大数及其位置。

4.从键盘输入一串字符,从下标为m的字符开始,取出n个字符(m和n从键盘输入),形成一个新字符串 5.实现字符串的拷贝

6.编写一程序,将一个字符串反序存放。

二、实习步骤

1.由键盘输入10个整数,将它们从小到大排序 #include void main(){ int a[10],t,i;int *p;printf(“输入十个数:n”);for(p=a;p

scanf(“%d”,p);for(i=0;i<10;i++)for(p=a;p

if(*p>*(p+1))

{

t=*p;

*p=*(p+1);

*(p+1)=t;}

for(p=a;p

printf(“%d ”,*p);}

2、将10个字符串(设其长度小于30)排序 #include #include void main(){ char cty[10][30],*str[10],*temp;int i,j,k;for(i=0;i<10;i++)

str[i]=cty[i];printf(“输入十个字符串:n”);for(i=0;i<10;i++)

gets(cty[i]);for(i=0;i<9;i++){

k=i;

for(j=i+1;j<10;j++)

if(strcmp(str[k],str[j])>0)

k=j;

temp=str[k];

str[k]=str[i];

str[i]=temp;} printf(“排序后:n”);for(i=0;i<10;i++)

printf(“%sn”,str[i]);}

2.将10个字符串(设其长度小于30)排序。

3.找出二维数组(设4行5列)中的最大数及其位置。

4.从键盘输入一串字符,从下标为m的字符开始,取出n个字符(m和n从键盘输入),形成一个新字符串 5.实现字符串的拷贝

6.编写一程序,将一个字符串反序存放。

C语言中指针链表的学习探讨 篇3

关键词:动态;链表

中图分类号:TP311.12

C语言中存储数据的结构用的最普遍的是数组,包括简单类型的数组,指针数据和结构体数组等,但是他们在实际应用中,会因为实现定义过大的数组容量而造成内存的浪费,或者因为保守的预测分配而满足不了实际使用的要求,这时就需要另一种方法来解决这个问题,这就是动态数据结构和动态分配内存技术。链表就是这样一种最简单的动态数据结构。那么如何让学生能够很好的学习并掌握它,本人就近几年的教学过程中经过探讨,采用了图示法进行教学,效果很好。

1 基本概念的理解

1.1 指针的理解

(1)指针与简单变量。通过图1所示理解指针与简单变量的关系,当把变量i的地址存入指针变量p1后,就可以说这个指针指向了该变量。

如需要指向下一个元素,只需要指针往后移动即可!

1.2 结构体的理解

(1)结构体类型。结构体类型是一种专门组织和处理复杂关系的数据结构,是一种自定义类型。同一个数据对象由于应用不同定义的类型也有所不同。比如处理学生的信息,可以有很多种方式:

结构体中的成员名可增,可减,形成新的结构体类型。

(2)结构体变量与数组。以上是结构体类型的定义,变量定义方式有三种,这里不一一举例,可根据自己的个人习惯选择不同的定义方式。比如上面两个类型,分别定义简单变量,可这样定义:

struct student s1,s2; struct stu s3,s4;

如定义数组,结合前面所学数组的知识,可这样定义:

struct student s[10]; struct stu s1[20];

2 指针链表

掌握了前面指针和结构体的知识内容,对于指针链表的理解和掌握是非常重要的。

2.1 指针链表的定义

这里主要讲解单项链表结点的结构体类型的定义,对于初学者掌握了这种定义,对于以后学习更为复杂的链表知识的理解是很有帮助的。

单项链表结点的定义:

struct node

{

int data; //存放的数据,可以定义其他更为复杂的数据结构

struct node *next; //指向struct node类型数据,用此建立链表

};

2.2 指针链表的建立

定义好类型后,再定义变量,并将链表建立起来,形成整数数据按升序建立的数据链,下面通过函数create来实现链表的建立。

struct node *create()

{

struct node *head,*p,*q,num;

head=NULL;

scanf("%d",&num;);

while(num!=0)

{

p=(struct node *)malloc(sizeof(struct node ));

if(p==NULL)

{

printf("Allocation failure\n");

exit(0);

}

p->data=num;

p->next=NULL;

if(head==NULL)

head=p;

else

q->next=p;

q=p;

}

return head;

}

2.3 指针链表的插入

链表建立完成后,最常用的操作之一就是对链表的数据进行增加,也就是插入操作,具体程序通过insert函数实现。

struct node*insert(struct node*head,sturct node*r,int*x)

{

struct nod *p,*q;

if(head==NULL)

{

head=r;

r->next=NULL;

}

else

{

p=head;

while(*x>p->data&&p-;>next!=NULL)

{

q=p;

p=p->next;

}

if(*xdata)

{

if(p==head)

head=r;

else

q->next=r;

p->next=p;

}

else

if(p==NULL)

{

p->next=r;

r->next=NULL;

}

return head;

}

2.4 指针链表的删除

对于链表中数据的删除也是链表数据中操作的重点,具体实现过程通过函数deletenode实现。

struct node*deletenode(struct node*head,int*x)

{

struct nod*p,*q;

if(head==NULL)

{

printf("This is a empty list.");

return head;

}

p=head;

while(*x!=p->data&&p-;>next!=NULL)

{

q=p;

p=p->next;

}

if(*x==p->data)

{

if(p==head)

head=p->next;

else

q->next=p->next;

free(p);

}

else

printf("NOT FOUND");

return head;

}

3总结

单向结点链表的主要操作就是建立,插入和删除数据,而且是链表当中最简单的一种形式,只有理解和掌握单向结点链表的基本操作,才有可能处理更为复杂的数据对象,在课堂上通过以上三个函数的编写与引导,学生对于链表有了初步的认识,并起到了良好的效果。

参考文献

[1]杜友福.C语言程序设计[M].北京:科学出版社,2012.

[2]龚民,朱秀兰.C语言程序设计教学探讨[J].电脑知识与技术,2009.

作者简介:刘山根(1976.8-),男,籍贯:河南新乡,职务:广东省华侨职业技术学校教务科副科长。

C语言指针应用 篇4

在C/C++程序中,对象(变量)存储在程序的内存空间中,并对应着惟一的地址。确切地讲,这个地址还跟对象(变量)的类型(auto,static,global,etc)有关。

同样,函数与对象(变量)相似,它也有自己惟一的地址与之对应。那么,就可以定义一个指针指向该地址(函数),这个指向函数的指针就叫做函数指针。与函数指针相似的一个术语是指针函数,表示其返回值是指针类型的函数。

2 定义

所有的C/C++中的对象(变量)必须经过定义才能够使用,函数指针也不例外。函数指针的定义与对象(变量)类似,略有不同。函数指针定义的一般形式为:

Return_Type(*Function_Fointer)(Argulist)。

示例(一):pointer to object pointer to function

注意函数指针定义中括号的使用保证了*和func_ptr的优先结合,否则func_ptr将变成一个返回值为指针的普通函数。函数指针中一个非常重要的问题是要保证函数指针的类型与它所指向的函数的一致性,比如示例一中func_ptr与f的返回类型和参数列表都是一致的,这样才不会报错。

函数指针的初始化和赋值有二种方式,第一种方式如示例一所示,对函数名使用取址运算符&。由于函数名本身就代表着入口地址,所以也可以直接把函数名赋给函数指针,那么示例一中可改为:int(*func_ptr)(int arg)=f。

示例(二)

运用typedef可以使函数指针的定义和使用更加方便和简洁。在示例二中,typedef的使用是程序更加明朗和可读。

示例(二)

typedef的功能是定义新的类型。示例二中第一句就是定义了一种PTRFUN的类型,并定义这种类型为指向某种函数的指针,这种函数以一个int为参数并返回char类型。后面就可以像使用int,char一样使用PTRFUN了。

3 使用

通过函数指针去调用函数有两种方法,包括隐性(explicit)和显性(implicit)调用。显性调用如示例三所示。隐性调用只需要将(*funcptr)(3,2)改为funcptr(3,2)即可。这两种方法完全是等同的,具体由个人爱好所决定。

4 应用

4.1 应用技巧

函数指针(function pointer)是一类特殊的指针,它在C/C++编程中有着广泛的应用。函数指针主要有两个方面的用途:调用函数和做函数的参数。利用函数指针作为参数和调用函数,就开创了许多程序设计中的可能和技巧,主要体现在以下3个方面:

(1)多态(polymorphism)。多态实现的机制十分复杂,其中虚函数表起着重要的作用。一般来讲,编译器会为数据结构加入一项成员,是一个指向虚函数表的指针(经常被称为vptr),而虚函数表中存放的是由函数指针组成的数组,函数指针指向实际所调用的函数。

(2)回调函数(call-back)。实现回调函数的关键是函数指针作为函数的参数。回调函数应用的非常广泛,例如Win32的Win Proc其实就是一种回调,用来处理窗口的信息。

(3)取代switch–case语句。switch-case语句在选择项数上和程序维护上有一定的限制,使用函数指针可以解决这一问题。

4.2 应用实例

4.2.1 消息映射雏形

Windows程序是以消息为基础的,其消息映射极其复杂,函数指针发挥着重要的作用。下面用一个简单的消息映射雏形来说明函数指针的使用方法和技巧。

定义一个MSGMAP结构和一个cou宏:

MSGMAP结构中第二个元素pfn是一个函数指针,以此指针所指的函数处理n Message消息。

设计一个数组_message Eneries[]把程序中预处理的消息以及消息处理函数的关联性建立起来。

可以看出,Wnd Proc函数永远不必改变,每当有新的要处理的消息时,只需在_message Entries[]数组中加入新的元素即可。而函数指针在整个消息映射中扮演十分关键的角色。

4.2.2 回调函数

回调函数是一个通过函数指针调用的函数。如果把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来用它所指向的函数时,就说这是回调函数。回调函数使用的场合很多,下面就通过一个简单回调函数实例来阐述函数指针在回调函数中的应用。

假设Barrel Volume是库函数中用来计算柱体体积的一个函数,定义如下:

由于不同类型柱体底面积的计算方法不一样,用户可以根据需要编写自己的面积计算函数,通过函数指针传递进去,增加了程序的维护性和简洁性。

如果用户计算圆柱的体积,可以这样编写:

其中Area0(),Area1()为回调函数。

5 结语

函数指针由于定义复杂,抽象难懂,使用技巧性强,是C/C++程序设计学习中的难点。,在程序设计的过程中,要认真思考,巧妙应用,克服函数指针的致命缺点(函数指针无法对参数和返回值的类型进行检查),利用函数指针设计出优秀的程序代码

参考文献

[1]汪明光.C++语言中函数指针的分析与应用.巢湖学院学报,2006,(3):30-33.

[2]李永祥,陈意云.基于函数指针数组的代码迷惑技术.计算机学报,2004,(12):1707-1708.

[3]侯俊杰.深入浅出MFC.武汉:华中科技大学出版社,2001.

c语言 二维数组与指针 教案 篇5

9.6二维数组和指针

2课时

掌握二维数组的地址表示方法 掌握指向数组元素的指针变量

掌握指向数组元素的指针变量

掌握用指向由m个元素组成的一维数组的指针变量

指向一维数组的指针变量

作业见后 一、二维数组的地址

例:定义二维数组int a[3][4]={{1,3,5,7},{9,11,13,15},{17,19,21,23}};

则二维数组a是数组的数组,由3个一维数组所组成的,即3个元素:a[0],a[1],a[2]。而每个元素又是一个一维数组。

二、指向二维数组元素的指针变量

1、指向数组元素的指针变量

例1 用指向元素的指针变量输出二维数组元素的值 #include void main()

{ int a[3][4]={1,3,5,7,9,11,13,15,17,19,21,23};

int *p;

for(p=a[0];p

{if((p-a[0])%4==0)printf(″\n″);

printf(″%4d″,*p); }

}用指向由m个元素组成的一维数组的指针变量

例2 输出二维数组任一行任一列元素的值 #include void main(){ int a[3][4]={1,3,5,7,9,11,13,15,17,19,21,23};

int(*p)[4],i,j;

p=a;

scanf(“i=%d,j=%d”,&i,&j);

printf(“a[%d,%d]=%d\n”,i,j,*(*(p+i)+j)); } 注意:

指向一维数组的指针变量的定义格式应写成:基类型(*p)[N] 上述语句int(*p)[4],代表p是一个指针变量,它指向包含4个整型元素的一维数组。*p两侧的小括号不可少,如果写成*p[4],由于[]运算级别高于*,*p[4]是指针数组。

p=a;表明p指向数组a中的第0行,此时p+1不是指向a[0][1],而是指向a[1],p的增值以一维数组的长度为单位,p+1地址就增加了8个字节。*(p+i)+j是a[i][j]的地址,这里的i是以一维数组的长度为单位,j则是以数组元素的长度为单位的。

复习

新授

讲授

复习默写

1、选择排序的基本思想

2、从键盘输入5个整数,使用选择法从小到大排序,编程实现。

一、二维数组的地址

例:定义二维数组int a[3][4]={{1,3,5,7},{9,11,13,15},{17,19,21,23}};

则二维数组a是数组的数组,由3个一维数组所组成的,即3个元素:a[0],a[1],a[2]。而每个元素又是一个一维数组。设二维数组的首行的首地址为2000,则:

二、指向二维数组元素的指针变量

1、指向数组元素的指针变量

例1 用指向元素的指针变量输出二维数组元素的值

#include void main()

{ int a[3][4]={1,3,5,7,9,11,13,15,17,19,21,23};

int *p;

for(p=a[0];p

{if((p-a[0])%4==0)printf(″\n″);

printf(″%4d″,*p); }

注意:上例中如果对p赋值p=a[0];不能写成 p=a;因为此时a 是行指针,而p是列指针只能指向一个整型变量,a[0]是第0行的数组名,即第0行的首地址就是a[0][0]的地址。请学生思考上述赋值语句还可以写成什么? p=*a;p=&a[0][0];用指向由m个元素组成的一维数组的指针变量 例2 输出二维数组任一行任一列元素的值 #include void main(){ int a[3][4]={1,3,5,7,9,11,13,15,17,19,21,23};

int(*p)[4],i,j;

p=a;

scanf(“i=%d,j=%d”,&i,&j); printf(“a[%d,%d]=%d\n”,i,j,*(*(p+i)+j)); }

注意:

指向一维数组的指针变量的定义格式应写成:基类型(*p)[N] 上述语句int(*p)[4],代表p是一个指针变量,它指向包含4个整型元素的一维数组。*p两侧的小括号不可少,如果写成*p[4],由于[]运算级别高于*,*p[4]是指针数组。

小结

作业

p=a;表明p指向数组a中的第0行,此时p+1不是指向a[0][1],而是指向a[1],p的增值以一维数组的长度为单位,p+1地址就增加了8个字节。*(p+i)+j是a[i][j]的地址,这里的i是以一维数组的长度为单位,j则是以数组元素的长度为单位的。

例3:

int(*t)[4],a[3][4]={{1,3,5,7}, {11,13,15,17},{21,23,25,27}};t = a;printf(“%d,%d”, **t, t[1][2]);t++;t++;printf(“%d”, **t);

运行结果:1,1521

【课堂小练习】

1、[2010.3.27]若有:int(*p)[3];则正确的是(D)A)定义了基类型为int的三个指针变量

B)p是基类型为int的具有三个元素的指针数组 C)定义了名为*p,具有三个元素的整型数组

D)定义了一个名为p的指针变量,它可以指向每行有三个整数元素的二维数组

2、输入:1 2 3<回车>,则输出结果是 int a[3][2]={0},(*p)[2],i,j;p=a;for(i=0;i<2;i++){ scanf(“%d”,p);p++;} for(i=0;i<3;i++)for(j=0;j<2;j++)printf(“%d”,a[i][j]);

1、二维数组的地址

2、指向数组元素的指针变量

3、指向一维数组的指针变量

1、整理课堂笔记

C语言指针探究 篇6

1 C语言能直接访问内存———通过指针机制实现

高级语言编程是与硬件无关的[1]。语言中的许多对象符号就是对硬件的抽象。比如, 变量名称就是对内存单元的抽象, 函数名、数组名也都是对相应内存单元的抽象代表。

我们都知道, 程序中首先要定义变量、数组, 这是为编译程序服务的。

例如:定义变量、数组语句如下:

int a, x[10];

在程序编译时, 编译程序就会分配内存单元给变量及数组, 以便日后数据存入变量和数组中。所以变量名、数组名就是内存单元的代名词, 正像身份证号码就是某人的代号一样。但是, 如果想直接对内存单元读写数据可以吗?高级语言能做到吗?回答是, C语言可以。进一步讲, C语言是通过指针机制实现的。同时, 也可以说, C语言通过指针机制做到编程中可以直接和内存这样的硬件打交道。也就是直接访问内存。接下来就对指针机制访问内存做详尽的说明。

2 指针变量做函数形参———能完成一石三鸟的功能

高级语言编写的程序, 需要翻译成二进制代码程序, 并装入内存单元中, 才能运行。编译程序做翻译工作, 链接程序和装入软件做链接和装入代码到内存单元的工作。翻译程序还有一个非常重要的工作, 就是把程序中所有的名字和内存单元对应起来, 形成一一映射关系。举例说明如下。

程序中定义变量如下:

假设, 程序在编译处理时, 给变量a分配的内存单元是2字节, 从2000H到2001H这2个字节单元;数组x, 编译程序给它分配的内存单元从3 000H~3 013H共40个字节单元;针对函数max, 编译程序给它分配的内存单元从5 000H开始的一系列单元。显然, 内存分配工作是编译程序来做的工作, 与编程者没有关系, 对编程者是透明的。但是, C语言可以和内存直接打交道, 具体如下:

int*p, a;

p=&a;

*p=12;

上述语句定义两个变量:p, a。

p:是指针变量, 用它存储变量a的内存地址。

a:是整型变量, 用它存储一个整数。

上述语句有两个关键的运算符:&, *。

&:是取地址运算符。&a, 代表变量a的内存地址。

*:是取值运算符。*p, 代表p的内容 (&a) 所标识的内存单元, 即a。

这里, 有三个值要区分。分别是:变量地址、变量值、指针变量的值。用下图表达其中的关系。

图1中, 矩形框代表变量的单元, 假设, p变量的内存单元地址是:&p (5 000H) , a变量的内存单元地址是:&a (2 000H) 。p的值是:&a, a的单元地址是:&a, a的值是12, 也是:*p。所以, 取值运算符*, 就是获取地址对应单元的数据。在这里, 运算符&, *是功能互逆的。所以*p就是a。因为, *p等于*&a即a。

使用指针变量p可以间接访问a的数据。因为, a变量的核心信息———内存单元地址, 已经在p内存单元中保存了, 所以访问a, 完全可以通过p变量实现。为什么要这样曲线使用a的信息呢?请看以下例子。

程序代码:

分析以上程序, 程序功能是交换主函数中变量a, b的值。函数swap的形参是指针类型变量, 为什么要这样?因为, 主函数中的变量a, b, 要在swap函数中使用, 直接写成如下形式是不行的。

因为, 第一种情况是, 主函数中变量a, b的作用域仅在主函数中, 不能越权在swap函数中使用它们。第二种情况下, swap函数中使用的变量a, b是自己的形参变量, 也是函数swap内的变量, 并不是主函数中定义的变量a, b。

所以, 以上两种代码都不能完成主函数中变量a, b的交换任务。但是, C语言提供了解决此问题的方法, 那就是指针。通过获取主函数中变量a, b的指针 (地址) , 并把它以实参的形式传递给函数swap, 函数swap就可以得到主函数中a, b变量的信息, 以便于使用它们。这就是用指针的形式间接访问主函数中变量a, b的手段。不能直接访问就采用迂回的、间接的指针方法。下面再举一例说明指针还可以用在什么地方。

程序代码如下:

程序说明:

程序中, 排序的数据希望是主函数中x数组中的100个整数, 但, 排序工作是sort函数来实现。这就面临两个问题。其一, 主函数中的数据要在另一个函数sort中使用和访问, 面临作用域超界问题。同时, 其二, 是100个整数要一一传递给sort函数, 显然, 传递工作量太大, 会消耗许多系统时间, 完成数据的传递工作。但是, C语言提供了解决方法, 还是指针。用指针变量做形参, 传递实参数据时, 把主函数中数组的首地址传过来即可解决上述两个问题。即, 用传首地址代替传100个数值;用传首地址的方法, 就可以间接访问主函数中数组x中的100个数据, 避开作用域限制[2]。显然, 用指针做函数sort的形参, 可以起到一石二鸟的作用。也解决并弥补了C语言用return语句只能返回一个数据的不足。所以在本环境下, 用指针做函数sort的形参, 可以说是一石三鸟。

3 指针和文件操作

通过文件指针操作文件, 大大方便编程者。

下面再举一例, 说明指针在文件操作中的应用。

程序如下:

程序解释如下:

程序功能是打开文件, 读取文件中的一个个字符, 并显示到屏幕上。在这里, 文件指针fp是编程者抽象访问文件内容的关键。从而使程序与硬件 (磁盘) 脱钩, 为编写程序提供了大大的便利。在这里文件指针就是硬盘中文件的抽象, 也是访问文件的武器。所有的文件操作细节交由库函数承担, 库函数借助文件指针抽象操作文件内容, 编程者工作量大大减轻。

4 指针带来程序效率

另外, 指针在链表中的应用, 使得在批量数据中删除、插入操作, 效率大大提高。不会出现顺序存储数据时大量数据移动现象[3]。

5 指针小结

指针就是内存单元的地址编号, 指针变量是用来存储其他对象地址的特殊变量。用指针可以间接访问变量, 可以突破变量作用域的限制, 去访问其他函数中定义的变量。同时也是提高程序效率的方法之一[4]。也是函数处理批量数据的解决手段。真正要用好指针, 解决实际问题, 需要掌握指针理论和多编程实践。

参考文献

[1] (美) Stephen Prata.C Primer Plus[M].第5版.云巅工作室译.北京:人民邮电出版社, 2013.

[2] (美) Ivor Horton.C语言入门经典[M]第4版.杨浩, 译.北京:清华大学出版社, 2010.

[3] (美) Kenneth A.Reek.C和指针POINTERS ON C[M].第2版.徐波, 译.北京:人民邮电出版社, 2008.

C语言的指针解析 篇7

1.1 指针

C语言中, 任何数据都会占用内存单元的。计算机内存的每个存储位置都对应唯一的存储地址, 而变量名作为变量数据存储区域所取的名字, 代表的是一个内存编号, 而这个内存编号对于用户来说是未知的。如定义:int a=12。

变量名a代表某个内存单元, 而变量值12则是这块内存单元里面的内容。在整个程序运行过程中, 通过变量名来访问变量, 变量名a所代表的这块内存单元不变, 所改变的只是这块内存单元里面的值。

C语言也支持使用变量存储地址来对变量进行存取操作, 要取得变量的存储地址, 可使用取地址运算符&, 如&a表示变量a的存储地址;而变量的存储地址就是指针。

1.2 指针变量

指针类型就是C语言中用于表示存储地址的数据类型, 而专门用来存放变量存储地址的变量则称为指针变量。

格式:数据类型 *指针变量名。跟普通变量不同的是, 所有指针变量占用的内存单元大小是一样的, 前面的数据类型代表的是指针变量所指向变量的数据类型。如以下代码:

1.3 二级指针变量

在C语言中, 任何值都有所对应的内存地址, 上述介绍的指针变量是指向普通变量的, 也就是普通的指针, 称为一级指针变量。

还有一种指针变量所指向的变量不是普通变量反而还是一个指针变量, 这种变量称为二级指针变量。如:

int a=12;//普通变量a

int *b=&a;//一级指针变量b, 指向普通变量a

int *c=&b;//二级指针变量c, 指向指针变量b

而这时, *c只是代表取c所指向的变量b里面的值:&a, 而a的地址又是未知的。所以, 对于二级指针变量c, 要想取出a的值, 必须需要两个间接访问运算符**, 如**c=** (&b) =*b=* (&a) =a。

2 指针与数组的关系

2.1 指针与一维数组

数组元素在内存中是顺序存放的, 并且数组名代表的是这一块内存单元的首地址, 数组其他元素的地址可以根据每个元素所占用的内存单元依次推知。因此, 一维数组的数组名实际上就是该数组的指针。如以下定义:

int a[10]={1, 2, 3, 4, 5};int *p=a;

此时, p指向数组中的第1个元素 (a[0]) , p+1指向第2个元素 (a[1]) , 依次类推。当然, p最开始也可以指向其他元素, 如指向第4个元素:p=&a[3];

在指针的运算中, 经常会跟自增或自减运算符结合起来使用, 如以下代码:

上述代码就是指针与数组之间关系的一个典型示例, 通过自增或自减运算符不光改变p的指向, 也可以改变p所指向的内存单元里面的内容 (也就是数组元素的内容) 。

2.2 指针与二维数组

由于二维数组可以看成是多个一维数组, 如以下定义:int a[3][4];可以把二维数组a看成3个长度为4的一维数组a[0], a[1], a[2] (假定二维数组按行存储) ;a[0]为第一个一维数组的数组名, 里面有4个元素:a[0][0], a[0][1], a[0][2], a[0][3];a[1]和a[2]依次类推。此时, 虽然二维数组名a和&a[0][0]表示的是同一个地址, 但是指向的却是完全不同的两种存储区域。a指向的是一维数组a[0]中4个元素的存储区域的首地址, &a[0][0]指向第一个元素a[0][0]的地址。此时的a相当于二级指针, a等价于&a[0], 而a[0]又等价于&a[0][0], 所以**a才等价于a[0][0], *a只是a[0], 而a[0]还是地址, 此值对于用户来说是未知的。如以下代码:

2.3 字符串指针

对于一维字符数组指针来说, 如前所述, 比较简单一些, 如以下代码:

但是对于二维字符数组指针, 相对来说复杂一些, 如以下代码:

3 指针作为函数参数

3.1 值传递与地址传递

在C语言中, 函数的参数传递有两种:值传递和地址传递。所谓值传递是指在函数调用时, 给形参分配内存单元, 把实参的值一一传递给对应的形参。但在函数执行中, 只是对形参变量进行处理, 形参值的改变对实参没有影响。而地址传递是指在函数调用时, 实参把数据的存储地址传递给形参, 使其指向同样的存储区域, 这样, 在函数执行中, 对形参的处理实际上就是对实参的处理, 形参值的改变对实参有影响。在C语言中, 地址传递一般通过指针或数组名来作为函数的参数。如以下代码:

在上述代码中, 函数swap1就是值传递, swap2就是地址传递, 调用swap1函数实参值不会做交换, 只有swap 2作交换, 代码的输出结果为:3, 5, 5, 3。

3.2 指针变量作为函数参数

指针变量作为函数形参也经常应用在数组作为实参的函数调用中。如以下代码:

针对数组或指向数组的指针, 各有两种表现形式:数组形式或指针形式。如:int a[10];数组的引用可以有常用的数组形式:a[2], 也可以有指针形式:* (a+2) 。同样的对于指向数组的指针, 如int*p=&a[2], 也有指针形式:* (p+2) 和数组形式p[2], 都等价于a[4]。

4结语

本文在简要介绍指针的概念和指针变量的基础上, 着重介绍了指针与数组的关系, 通过示例说明了指向一维数组的指针以及二维数组的指针, 特别是二维数组名作为二级指针的引用和字符串指针的应用;最后介绍了值传递与地址传递以及指针作为函数参数的应用。

摘要:C语言作为计算机类专业一门重要的基础课程, 是学生学习程序设计的开端, 后续专业课程大多以此作为前提。而在C语言的学习中, 指针又是一个重点以及难点。文章首先介绍了指针的概念以及指针变量的定义, 其次重点介绍了指针与数组之间的关系, 最后介绍了值传递以及地址传递的区别以及指针变量作为函数参数的应用。

关键词:C语言,指针,指针变量,地址传递

参考文献

[1]吉顺如.C语言程序设计教程[M].北京:机械工业出版社, 2011.

[2]李师贤, 译.C++Primer中文版:第4版[M].北京:人民邮电出版社, 2006.

C语言教学中指针浅析 篇8

一、使用电子教室配合多媒体教学

C语言程序设计是一门实践性极强的课程, 传统的课堂教学往往使学生在听课的过程中感到极为吃力, 几乎完全不能理解教师所讲解的内容。而C语言中的指针又是C程序设计中的一个重点也是一个难点, 概念抽象, 学生更是难以理解。在我们的教学中采用将学生分组带进实验室进行实际的多媒体配合电子教室进行和教师同步教与学的方法。让教师一边演示一边讲解, 使指针的教学由枯燥、晦涩变得生动活泼起来, 加深学生对指针的理解和掌握, 比如说针对以下两个问题的教学。

1、什么是指针

指针实质是代表某一个内存单元的地址, 是内存单元的编号;在C语言的译系统中, 对于变量的访问形式之一, 就是先求出变量的地址, 然后再过地址对它进行访问, 这就是指针, 变量的指针就是指该变量所占用的内存单元的首地址。

2、什么是指针变量

指针变量是存放内存单元编号的变量, 或者说指针变量就是存放地址的变量。比如说有这样的定义:

int*i_point;;

在这里point是变量的名字, int*代表i_point这个变量存放的是int型变量的地址。再作如下定义:

int i=10

i_point=&i;

为了让学生彻底理解指针变量和指针是两个不同的概念, 教师可以制作出有趣的PPT动画进行演示。

二、指针教学中学生容易犯的错误

1、指针变量未初始化

学生在学习的过程中定义好一个指针变量后, 常常会忘记对其进行初始化操作。在C语言中, C语言的变量, 都是先定义后使用, 而C中的指针变量却有所不同, 指针变量在使用前, 不仅要先定义, 还要进行初始化也就是要对对指针进行赋值。如果没有对指针变量进行初始化, 那定义的指针变量就不具有具体的指, 将会随机指向内存单元中的某个地址, 如果不幸指向系统区中, 就会造成灾难性的后果。所以必须对指针变量进行初始化。

在这个程序中, 指针变量*point没有经过赋值操作, 就很容易造成计算机系统的灾难性崩溃!

2、对指针变量直接进行赋整数值

运行结果为:10, 20

10, 20

本程序定义了两个指针变量g1和g2, “g1=&i;和g2=&j;”语句是将i与j的地址分别赋给g1和g2, 不能写成“*g 1=&i;和*g 2=

&j;”。

与指针相关的两个运符:

(1) &:取地址运算符。

(2) *:指针运算符或称间接访问运算符, 取指针所指向的目标值。

“&”与“*”运算符的优先级别相同, 按自右而左的方向结合, 如“g1=&i;”语句, 若&*g1, 先进行的是*g 1的运算, 再执行&运算。

如:*&i的含义是什么?当然先进行&i运算, 得到i的地址, 再进行*运算。

三、指针与数组的安全性

C语言指针简化教学思考 篇9

关键词:C语言,数组,教学,指针

在C语言的教学中, “指针”这一部分内容一直是C语言的教学重点和难点, 直接影响学生对后续课程的学习和把握[1,2,3]。作为软件开发入门课程, 绝大多数时间是在讲条件、循环、数组、函数, 而指针内容却是省、国家计算机二级、程序员等考试的必考内容。为了在最短的时间内达到较好的教学效果。笔者从多年的教学经验认为C语言的指针教学应该注意以下几点:

一、输入函数scanf () 和数组中地址的应用

所有的书本上都有介绍scanf (格式控制字符串, 输入项列表) , 此函数的输入项列表要用“&”加变量名, 要将所输入的内容放入变量的地址中, 其中格式控制串中如果有普通字符也要输入普通字符, 且有很多输入后不能正确读取的情况, 初学者往往感到非常困惑难以理解。其实, 连续定义的多个变量在内存中也是占用连续的内存单元, 只是不同的数据类型所占的字节不同, 程序在运行过程中遇到第一个scanf () 函数时, 将要求用户从键盘上按要求输入内容, 所有输入的内容都将先放入缓冲区且你可以输入很多内容, 输入完成后再按scanf的格式控制字符串的格式来存入到变量的地址中, 一旦输入不合法, 则认为输入结束, 后面的变量将取不到值。如:scanf (“%d:%d”, &a, &b) ;若输入时你输入3, 4↙其中a的值为3, 输入格式串中本来要求你输入的是“:”而你输入的是“, ”, 明显不合法, 则scanf函数输入结束, 后面的变量b将取不到值。同时这也很好解释了若程序中有多个scanf函数时, 为了保证每次输入都有效, 则应该在输入函数前加一个清空缓存函数fflush (stdin) 。

数组名代表的是数组的首地址, 所以在scanf () 函数中以”%s”为格式串所对应输入项列表不需要加“&”。如:char str[20];

scanf (“%s”, str) ;/*将输入的内容存储到从数组首地址开始的地址中*/

printf (“%s”, str) ;/*从数组的首地址开始输出字符数组的内容*/。

这些内容都与计算机的实际存储有关 (即和地址有关) 。

二、指针

指针就是地址。其实前面我们在讲解输入输出函数和数组时, 我们就介绍了一些有关地址的应用。一听自己已经用过且有所接触了, 学生也就不会感到太畏惧了。再加上时间有限, 我们要言简意赅地说明指针的用法。

1. 指针的概念。

指针就是内存地址。这里首先要区分三个比较接近的概念:名称、地址和内容 (值) 。名称是给内存空间取的一个容易记忆的名字;内存中每个字节都有一个编号, 就是“地址”;在地址所对应的内存单元中存放的数值即为内容或值。

为了帮助读者理解三者之间的联系与区别, 我们不妨打个比方, 有一座教师办公楼, 各房间都有一个编号, 如101, 102, …, 201, 202, …。一旦各房间被分配给相应的职能部门后, 各房间就挂起了部门名称:如电子系、计算机系、环境工程系等, 假如电子系被分配在101房间, 我们要找到电子系的教师 (内容) , 可以去找电子系 (按名称找) , 也可以去找101房间 (按地址找) 。类似地, 对一个存储空间的访问既可以指出它的名称, 也可以指出它的地址。

在C语言中, 如果变量p中的内容是另一个变量i的地址, 则称变量p指向变量i, 或称p是指向变量i的指针变量, 形象地用图1所示的箭头表示。

由此可以得出结论:变量的指针即为变量的地址, 而存放其他变量地址的变量是指针变量。

指针变量是一种变量, 因而也具有变量的三个要素, 但它是一种特殊的变量, 其特殊性表现在它的类型取值上。具体而言: (1) 变量名:与一般的变量命名规则相同。 (2) 变量的值:是某个变量的内存地址。 (3) 变量的类型:主要是其指向的变量的类型。

2. 指针指向简单变量。

如:int a=100, *p;/*指针变量的定义*/

p=&a;/*指针变量的赋值*/

*p=200;/*指针变量的应用*/

printf (“%d”, a) ;则输出值为200。

在此我们要理解指针一旦定义且指向了一简单变量, 除定义和初始化时的*p, 其他的*p等价于它所指向的简单变量 (即这里的*p<=>a) , p (指针) 等价于简单变量的地址 (即这里的p<=>&a) 。上面的输出语句可以变为:printf (“%d”, *p) 。

3. 指针指向数组。

(1) 指针指向一维数组。

如:int a[5]={10, 20, 30, 40, 50}, *p=a;p++;

printf (“%d, %d, %d”, *p, * (p+2) , *p++) ;则输出结果为:30, 50, 20

以上是指针指向一维数组的基本应用, 首先我们要理解有关指针的运算。

&:取地址运算符[5]。

*:指针运算符 (间址访问运算符) , 取指针所指向的值, 若所指向二维数组则表示离取值进了一步。

++:算术运算符, 表示指针往下或右移一个单位 (其中这个单位和具体的数据类型有关, 如果是整型数一个单位就指2个字节, 实型指4个字节) 。

--:算术运算符, 表示指针往上或左移一个单位。

若定义了一个指针指向了一个一维数组, 则p<=>a的使用 (原来的a[i], 也可以用p[i]表示, *p<=>*a) , 即* (p+i) <=>a[i]<=>p[i]<=>* (a+i) 。但要注意p和a同为地址它们是有区别的, p为变量地址, 而a是常量地址。有p++而不能用a++。

(2) 指针指向二维数组。对于指针指向二维数组, 要理解行地址和列地址的含义 (*运算符能实现行地址向列地址的转换) 再加上一维数组中的等价关系, 能理解下面的二维数组的指针表示形式表即可。

(3) 数组指针与指针数组的含义。前者是指针, 后者是数组。定义格式:仅差一对圆括号。 (1) 指向一维数组的指针。假设有定义语句:int (*p) [4]; (2) 指针数组。假设有定义语句:int*p[4];

(4) 应用场合:前者是一个指针, 后者是多个指针。 (1) 指向一维数组的指针。一般将一个二维数组名赋值给一个指向一维数组的指针, 来访问二维数组中的某一行。 (2) 指针数组。适合存放若干个字符串, 使字符串的处理更加方便灵活。例如:

用字符指针数组处理字符串不仅可以节省内存, 还可以提高运行效率。

4. 指针指向函数。

(1) 指针作为函数的参数。

其中左边交换完后, 能传递给实参, 因为它是指针所指向的值发生交换, 而右边只是指针的指向发生改变原本值未发生交换。

(2) 指针函数与函数指针。这是两个完全不同的概念, 前者是函数, 后者是指针。

a定义格式:仅差一对圆括号。

(1) 指针函数。假设有定义语句:

int*fp (int x, int y) ;

(2) 指向函数的指针 (函数指针) 。假设有定义语句:

int (*fp) (int x, int y) ;

b应用场合:前者是一个函数, 只是函数的返回值是指针;后者是一个指向函数的指针, 通过这个指针可以间接地调用所指向的函数。

三、总结

本文探讨了指针教学中, 通过截取最基本且最重要的知识来解析其应用问题, 目的在于使学生在较短的时间内掌握其基本知识, 预计可作为指针教学的有效方案之一。

参考文献

[1]管银枝.C语言程序设计实例教程[M].北京:人民邮电出版社, 2011.

[2]谭浩强.C程序设计 (第二版) [M].北京:清华大学出版社, 2001.

C语言指针的研究与运用 篇10

关键词:C语言,指针,数组,函数

指针是C语言中的精髓,它在C语言中被广泛的使用。理解和运用好指针可以灵活方便地处理程序中各种复杂问题,可以轻松完成其他高级程序设计语言不便完成的任务。

一、指针的概念

一个指针变量的值就是某个内存单元的地址或称为某内存单元的指针。

指针的引入为系统存取数据提供了一种“间接访问”方式。所谓间接访问,是先访问存放变量地址的存储单元,得到该变量的地址,再对变量内容进行访问。

指针变量是一种特殊变量。系统为指针变量分配一块连续存储单元不是供其存储数据,而是存储内存地址。因此,指针变量是存储内存地址的变量。

二、指针的类型

1、指向简单变量的指针。指针所知的数据类可以使简单的数据类型。

例:(1)int*p,i;p=&i;意思是指针变量指向整型变量i

(2)char*p,a;p=&a;意思是指针变量指向字符型变量a

(3)int*p,a[10];p=a;意思是指针变量指向数组a

2、指向数组的指针。指针所指的数组既可以是一维数组,也可以是多维数组。

分析:指针P指向了a数组的首地址,通过p++来访问a数组的每一元素。

3、指针数组。数组元素是由指针变量组成的一种指针。定义如:nt*p[2];指针数组p包含两个元素,每个元素指向一个整型数据。

分析:指针P是一个数组,通过for循环语句给指针数组中的每个指针变量赋值,p[1]的初值为数组a的第二行的首地址,*(p[1]+1)便是元素a[1][1],因此程序输出7。

4、指向指针的指针。指针变量指向的是指针的地址,定义如:int**p。

分析:指针数组p的各个指针变量指向数组a的各行首地址,q指向指针数组p的首地址,*(q+1)等同p[1],如此,*(*(q+1)+1)便等同*(p[1]+1)也就是a[1][1],因此程序输出7。

5、指向函数的指针。指针变量指向函数的首地址,然后通过该指针变量调用该函数。定义如:int(*p)()。

分析:int (*p)()表示定义了一个指向函数的指针变量,函数名max代表了函数的入口地址,执行p=max后,p指向了函数max,(*p)(a,b)便是通过p调用函数max。

6、指向文件的指针。C语言对文件的操作并不是直接通过文件名进行的,而是根据文件名生成一个文件指针,通过该指针来对文件进行操作.定义如:FILE*fP(fp为文件指针,此时fp不指向任何文件)。

三、指针应用中常见的错误

1、把数据赋给指针变量。指针在使用前必须进行初始化,赋予指针的值必须是地址。

正确语句:p=&i;“&”是一个取变量地址的运算符。

2、指针常量运算错误。程序中常量指针是不能被修改的。典型有数组名指针常量和指向字符串常量的指针。

3、指针赋值类型不一致

正确语句:p=a[0];或p=&a[0][0];如果一定把a赋值给p,必须先将a转换成整型指针类型,如:p=(int*)a;。特别是将多维数组赋值给指针变量时应注意类型匹配。

参考文献

[1]陈建辉,C语言指针探讨[M]·莆田高等专科学校学报,2001

[2]施冬梅,C语言指针教学中应注意的几个方面[M].镇江高专学报,2004

上一篇:消费者保护下一篇:复杂图像