C语言中的指针运算

2024-05-20

C语言中的指针运算(精选8篇)

C语言中的指针运算 篇1

1 引言

C语言是使用最广泛的程序设计语言之一,它以功能强大,语言简练,编程灵活等特点为广大程序设计人员所青睐,但对初学者是有一定难度的。尤其是指针,它既是C语言的一个重要特色,又是C语言的重点和难点。正确而灵活的使用指针,可有效的表示复杂的数据结构、动态分配空间、方便引用字符串和数组、在函数调用中获得多个返回值、并且可以直接处理内存地址等等。正是因为指针太灵活,一旦指针使用不当,将会导致程序出错,甚至造成系统崩溃。因此,要编写出正确高效的程序,正确理解和使用指针,以及了解指针使用的常见错误是很有必要的。

2 指针的理解和使用

2.1 指针的理解

理解语言指针的基础就是牢固树立指针就是地址的概念。明确地说,指针常量就是地址常量,指针变量就是地址变量。

我们先来看看指针常量:

1)若a是整型常量,则&a表示是a的地址,因为常量的地址在内存中是固定的,因此,是&a指针常量。

2)对于数组来说,只写数组名表示数组的首地址,而数组在内存中的位置是不能改变的,所以它也是指针常量。

3)对于字符串常量来说,直接写出某一字符串就是表示是该字符串的首地址,这是许多教科书上未能提到的。字符串常量在内存中有固定的位置,字符串常量的地址也属于指针常量。

4)对于某个函数来说,它在内存中的地址也是固定的。这样,函数的地址也属指针常量,在C语言中,函数名可以表示函数的地址。

再来看看指针变量:

指针变量就是地址变量,就是说,它是用来存放某一类变量地址的变量。有此概念以后,我们就容易理解指针数组的元素是用来存放变量地址的。同样,在处理链表、二叉树这类递归数据结构时,相应的结构中应存放其它结点的地址从而形成链接的成员变量,即该成员变量应是地址变量,必须用指针变量来刻画。

对于指针变量来说,C语言提供了“*”运算符,它表示取该变量的内容,而当指针变量是指向某一函数时,这时的“取内容”,应广义的理解,即执行相应的函数。

2.2 指针的使用

在程序中定义一个变量,C语言编译系统就会根据该变量的数据类型,为其分配相应的存储单元,类型不同所分配的存储单元的字节数也是不同的。指针变量是一种特殊类型的变量,定义一个指针类型后,C语言编译系统便会为该指针变量分配一个存储单元,用于存放相应变量的地址。使用该指针变量时,必须保证该指针变量指向一个明确的存储单元,即被赋值。例如:

使用指针时,常常涉及到两个运算符:

1)&:获取存储单元的地址

2)*:获取指针变量所指向的存储单元的内容

例如,&i表示变量i的地址,*p表示指针变量p所指向的存储单元的内容,即变量i的内容为2。

2.3 指针变量的类型

指针变量与一般变量一样,也有类型。指针变量的类型是指针所指向的数据的类型,我们也称指针变量类型为指针变量的基类型。指针变量的基类型不仅仅是指所定义指针变量的类型修饰符,同时还包含该指针变量是对多大的存储空间进行解释。例如:

int*p1,(*p2)[3],(*p3)[2][3];

其中,p1可指向1个int型的存储单元,p2可指向3个int型的存储单元,p3可指向6个

int型的存储单元。因此,p1+1是p1指针向下移动2个字节(基本整型占用2个字节),p2+1是p2指针向下移动6个字节(p2指向3个int型的存储单元,每个存储单元占用2个字节,即3×2),p3+1是p3指针向下移动12个字节(p3指向6个int型的存储单元,每个存储单元占用2个字节,即6×2)。

我们知道可以有下列语句定义指针与数组:

那么把两者结合起来会怎么样呢?

int*pa[3];

是定义成数组呢?还是定义成指针呢?回答这个问题的关键在于运算符的优先级。因[]的优先级高于*,加上括弧后定义变成

int(*(pa[3]));

所以pa究竟定义成什么,只要从内层依次往外层看就可以了。即pa是数组,由三个元素组成,每个元素是指针,是指向int型的指针。综合起来,pa是由三个指向int型的指针所构成的数组。

所以对于一个复杂的定义,我们可以按以下步骤来理解它:

1)根据优先次序,加上必要的括弧,使变量名在最内层。

2)从最内层开始依次往外层看,写上所看到的内容。

如:*—→指向×××的指针

[n]—→有n个元素的数组

()—→返回×××的函数等等

例如,对于int**pp;

1)加括弧int(*(*pp));

2)pp是指针,是指向指针的指针,该指针是指向int型的。

3)所以,pp是指向int型指针的指针。

注意,这时不要被两个*所困惑。pp也只不过是一个指针变量而已。请看下面的操作:如图1:

int i;

int*p;

int**pp;

pp=&p;/*把指向int型的指针变量p的地址放入pp所在的内存单元*/

p=&i;/*把int型变量i的地址放入p所在的内存单元*/

**pp=2;/*把整数2放入变量i所在的内存单元*/

现在我们知道,编绎系统不能区分简单指针和指向数组元素的指针。换句话说,对指针进行操作的时候,对指针指向的具体对象不能加以区分。如上面的pp是指向一个int型的指针变量的,而在下面的例子中,pp就指向了一个指针数组。如图2:

当然还有pp指向其它对象的可能。所以定义了1个指针以后,要记住它究竟是指向一个简单的对象呢?还是指向数组?这就要由编程序者自己掌握了。

再看下面的例子:

int(*pa)[3]:

按我们先前介绍的方法去理解,可知pa是一个指向由三个整型元素组成的数组的指针,通过下面的语句可以对它进行初始化。如图3:

3 指针使用中常见的错误

指针类型有其独特的特点,正确合理的使用可以提高程序的功能,但错误地理解和使用指针,将导致无法想象的结果。下面分析讨论指针使用中常犯的错误。

3.1 指针变量未赋值

指针变量在使用之前必须赋初值,这个初值应该是一个地址量。如果只是定义了一个指针变量而没有为它赋值,此时,指针变量指向的是一个不明确的存储单元。例如:

int*p;

*p=8;/*错误*/

该例中,将10赋值给p指向的存储单元,而p指向哪个存储单元是不确定的。应该改为:

这样指针p就指向了变量a,*p=10,实际上是将10赋值给变量a。或者也可以先调用C语言中的内存分配函数得到相应的存储空间,再将函数返回的首地址赋值给指针变量。即:

因此,对应指针变量一定要保证:先给指针变量赋值,然后再使用。

3.2 指针类型不匹配

在给指针变量赋值时,只能将与指针变量基类型相同的变量的地址赋值给改指针变量。例如:

例子中,指针pa的基类型为int型,指针pb的基类型为float型,只能将int型变量的地址赋值给pa,将float型变量的地址赋值给pb。应改为:

另外,基类型相同不仅仅是指类型相同,还包含系统分配给这种基类型的存储单元的容量也相同。例如:

此例中,p1=a是错误的,原因是p1与a的基类型是不同的,p1的基类型是含有1个int型的存储单元,a是二维数组名,是地址常量,它总共有2行,每行3个元素,因此它的基类型是含有3个int型的存储单元。其中,p2的基类型是含有3个int型的存储单元,p2与a的基类型是相同的,因此可以把a赋值给p2,这样就正确了。所以,在给指针变量赋值时,要考虑基类型是否匹配。

3.3 指针变量所指示的存储单元越界

当指针变量对所指示的存储单元进行操作时,应保证所操作的存储单元应该是已分配给程序的存储单元,不应该越界,否则将会导致严重的后果。例如:

第一个for循环用于给数组a的5个元素赋值,第二个for循环用于把数组a的5个元素输出,看上去好像没错,但输出的结果却是出现了问题,程序中存在严重的错误,原因是程序开始p指向数组a的首地址,当第一个for循环执行结束时,p指向数组a的末尾,因此第二个for循环开始执行时,p指针的值并不是&a[0],而是a+5,其值超过了系统给数组分配的空间,应该在第二个for循环前面加上一条语句:

p=a;

使p指针再重新指向&a[0],这样结果就正确了。

因此,在使用指针变量时,一定要注意指针变量应在系统所分配存储空间使用,不要超过系统分配的空间范围,否则结果是无法预料的。

3.4 指针函数带回的指针不存在

函数的返回值不仅可以是一般的数据类型,还可以为指针类型,这种带回的类型为指针的函数称为指针函数。对于函数带回的指针,这个指针所指示的存储单元应该是存在的,不可以不存在。例如:

max是指针函数,编写该函数的本意是由指针P带回x、y中较大数的地址,但函数max执行完毕,返回主函数main时x、y所占用的存储单元已被释放,而p带回的将是一个不存在的存储单元,这样做显然是不正确的。因此,程序应该改为:

这样修改后,max函数中的指针p带回的则是主函数main中a、b中较大数的地址,就可以正确输出了。可见指针函数中带回的指针应该是主调函数中变量的地址,不能是已释放空间的地址。

4 小结

指针是C语言的重要概念,是C语言的重要特色,它简洁、灵活、高效,但又有风险。正确理解和使用指针,避免常见错误发生,不仅要小心谨慎,还有多编程,多上机调试,弄清细节,发现错误,积累经验。

摘要:指针是C语言的一个重要概念,文章对指针基本概念和使用作了简单介绍,总结了指针在使用过程中常犯的错误,讨论了出错的原因,指出正确使用指针的方法,并阐述了C语言中的指针与数组、函数等结合起来的指针及其应用。

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

参考文献

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

[2]冯博琴等.C语言学习指南[M].北京:北京机械工业出版社,1996.

[3]田淑清.全国计算机等级考试二级考试教程-C语言程序设计[M].北京:高等教育出版社,1998.

C语言中的自增自减运算符的应用 篇2

关键词:C语言;自增(自减)运算符;表达式

中图分类号:G642 文献标识码:B 文章编号:1002-7661(2014)21-009-01

C语言功能强大,使用灵活,是初学者的很好的入门语言。而自增(自减)是C语言中比较有特色的运算符,在编程中合理使用可以节省代码,提高效率;但是如果使用不当,则极易造成错误。本文根据自增(自减)运算符的特点, 浅谈自增(自减)运算符在VC++6.0编译器的应用,以期为初学者学习和使用自增(自减)运算符提供一些帮助。

一、自增(自减)运算符的含义及使用形式

1、自增自减运算符的含义

C语言的自增和自减运算符分别是:++,--。作用是使变量的值加1或减1,它们能操作的对象只能是变量,常量不能进行自增(自减)运算。如7++相当于7=7+1,和赋值表达式的要求不相符。特别要注意的是在C语言中,数组名和函数名都属于常量,因此不能进行自增(自减)运算。表达式也不能进行自增(自减)运算。如(a+b)--,等价于a+b=a+b-1,不符合赋值表达式的要求。自增(自减)运算符具有对运算量重新赋值的功能,故不能对无存储空间的对象进行重新赋值。

2、自增(自减)运算符的使用形式

自增(自减)运算符作用于变量之前称为前缀运算(++i或--i),运算符作用于变量之后称为后缀运算(i++或i--)。前缀运算规则为:“先变后用”,即,加(减)号在前,先加(减)后用;运算结果:变量的值相应增加1(减少1)。后缀运算规则为:“先用后变”,即,加(减)号在后,先用后加(减);运算结果:变量的值相应增加1(减少1)。

二、自增(自减)运算符的灵活运用

“++、--”运算符在 C 语言程序中的运用非常广,也非常灵活,现通过例子说明。

1、自增(自减)运算符在表达式中的应用

例 #include

void main()

{int i=3,j=3,p,q;

p=++i;①

q=j++;②

printf("%d,%d,%d,%d\n",p,q,i,j);}

运行程序,输出结果为:4,3,4,4

分析:①是前缀,“先变后用”。即先执行i=i+1,在执行p=i。因此i和p的值都是4。②是后缀,“先用后变”。即先执行q=j,在执行j=j+1。因此q的值为3,j的值为4。

2、自增(自减)运算符的混合应用

设i的初值为4,求表达式p=(i++)+(i++)+(i++);自增运算作为后缀式,其运算优先级低于求和运算。相当于先执行p=i+i+i,在执行i++,i++,i++。因此p的值为12,i的值为7。

而表达式p=(++i)+(++i)+(++i);自增运算作为前缀式,其运算优先级高于求和运算。故先按照“自右至左”的结合性进行两次自增运算即++i,++i,i的值变为6,获得满足第一个求和运算符两侧的操作数要求进行6+6求和运算,然后将和值(12)与变量i的第三次自增值(i=7)进行第二次求和运算(12+7)即p=((++i)+(++i))+(++i)=(6+6)+7=19,最后i的值为7。

关于自增(自减)运算符的在混合应用中的规则我们可以理解为,若作前缀形式,其运算优先级高于其它算术运算,即先按照“从右至左”的结合性进行自增(自减)运算,再进行其它运算;若为后缀形式,其运算优先级低于其它算术运算,即先进行其它算术运算,再按照“从右至左”的结合性进行自增(自减)运算。

3、自增(自减)运算符在函数调用中的应用

在调用函数时,对函数参数的求值顺序是自右至左。

例如:i=4; printf("%d,%d",++i,++i);

上面printf函数中遵循从右至左的求值顺序,先求出第2个表达式 ++i 的值 5,然后求第1个表达式++i的值6,最后再从左到右输出每个表达式++i的值:6,5。

i=4; printf("%d,%d",i++,i++);

上面输出函数执行顺序仍为从右向左,第2个表达式i++的值为4,此时变量i并没有立即自增,,所以第1个表达式i++的值仍为4。最后再从左到右输出每个表达式i++的值:4,4。当输出函数执行完成之后,变量i执行i++操作,一共执行了2次,i的值为6。

4、自增(自减)运算符在循环结构中的应用

在循环语句while,do while和for中都有类似“i++;”或“i--;”这样由变量和自增自减运算符构成的赋值语句充当使循环趋于结束的语句,目的是为了避免程序出现死循环。

例#include

Void main()

{int s=0,i;

for(i=1;i<=20;i++)

s=s+i;

printf("%d\n",s); }

分析:当循环变量i=21时,条件不成立,循环结束。

在循环表达式中出现的自增自减运算符可看做独立的语句,++i 和i++最终都使得循环变量i的值自增,所以没有分别,等价于i=i+1。

三、结束语

自增、自减运算符是 C 程序设计语言中特有的,在编程过程中经常用到,但对于初学者而言,往往感到难以理解这两个运算符的运算实质,因此使用自增自减运算符时要特别小心,仔细考虑,否则会得到莫名其妙的结果,对于初学者在学习中应该多分析,同时也应多上机练习。希望通过对此所作的探讨,能够使初学者正确理解自增、自减运算符的作用和意义。

参考文献:

[1] 谭浩强.C程序设计[M].3版.北京:清华大学出版社,2005.

[2] 梁海英.C语言程序设计.清华大学出版社.2013

[3] 朱承学.C语言程序设计教程 [M].中国水利水电出版社.2004.

摘 要:自增、自减运算符是 C 程序设计语言中特有的,在编程过程中经常用到。本文根据自增(自减)运算符的特点, 浅谈自增(自减)运算符在VC++6.0编译器的应用,以期为初学者学习和使用自增(自减)运算符提供一些帮助。

关键词:C语言;自增(自减)运算符;表达式

中图分类号:G642 文献标识码:B 文章编号:1002-7661(2014)21-009-01

C语言功能强大,使用灵活,是初学者的很好的入门语言。而自增(自减)是C语言中比较有特色的运算符,在编程中合理使用可以节省代码,提高效率;但是如果使用不当,则极易造成错误。本文根据自增(自减)运算符的特点, 浅谈自增(自减)运算符在VC++6.0编译器的应用,以期为初学者学习和使用自增(自减)运算符提供一些帮助。

一、自增(自减)运算符的含义及使用形式

1、自增自减运算符的含义

C语言的自增和自减运算符分别是:++,--。作用是使变量的值加1或减1,它们能操作的对象只能是变量,常量不能进行自增(自减)运算。如7++相当于7=7+1,和赋值表达式的要求不相符。特别要注意的是在C语言中,数组名和函数名都属于常量,因此不能进行自增(自减)运算。表达式也不能进行自增(自减)运算。如(a+b)--,等价于a+b=a+b-1,不符合赋值表达式的要求。自增(自减)运算符具有对运算量重新赋值的功能,故不能对无存储空间的对象进行重新赋值。

2、自增(自减)运算符的使用形式

自增(自减)运算符作用于变量之前称为前缀运算(++i或--i),运算符作用于变量之后称为后缀运算(i++或i--)。前缀运算规则为:“先变后用”,即,加(减)号在前,先加(减)后用;运算结果:变量的值相应增加1(减少1)。后缀运算规则为:“先用后变”,即,加(减)号在后,先用后加(减);运算结果:变量的值相应增加1(减少1)。

二、自增(自减)运算符的灵活运用

“++、--”运算符在 C 语言程序中的运用非常广,也非常灵活,现通过例子说明。

1、自增(自减)运算符在表达式中的应用

例 #include

void main()

{int i=3,j=3,p,q;

p=++i;①

q=j++;②

printf("%d,%d,%d,%d\n",p,q,i,j);}

运行程序,输出结果为:4,3,4,4

分析:①是前缀,“先变后用”。即先执行i=i+1,在执行p=i。因此i和p的值都是4。②是后缀,“先用后变”。即先执行q=j,在执行j=j+1。因此q的值为3,j的值为4。

2、自增(自减)运算符的混合应用

设i的初值为4,求表达式p=(i++)+(i++)+(i++);自增运算作为后缀式,其运算优先级低于求和运算。相当于先执行p=i+i+i,在执行i++,i++,i++。因此p的值为12,i的值为7。

而表达式p=(++i)+(++i)+(++i);自增运算作为前缀式,其运算优先级高于求和运算。故先按照“自右至左”的结合性进行两次自增运算即++i,++i,i的值变为6,获得满足第一个求和运算符两侧的操作数要求进行6+6求和运算,然后将和值(12)与变量i的第三次自增值(i=7)进行第二次求和运算(12+7)即p=((++i)+(++i))+(++i)=(6+6)+7=19,最后i的值为7。

关于自增(自减)运算符的在混合应用中的规则我们可以理解为,若作前缀形式,其运算优先级高于其它算术运算,即先按照“从右至左”的结合性进行自增(自减)运算,再进行其它运算;若为后缀形式,其运算优先级低于其它算术运算,即先进行其它算术运算,再按照“从右至左”的结合性进行自增(自减)运算。

3、自增(自减)运算符在函数调用中的应用

在调用函数时,对函数参数的求值顺序是自右至左。

例如:i=4; printf("%d,%d",++i,++i);

上面printf函数中遵循从右至左的求值顺序,先求出第2个表达式 ++i 的值 5,然后求第1个表达式++i的值6,最后再从左到右输出每个表达式++i的值:6,5。

i=4; printf("%d,%d",i++,i++);

上面输出函数执行顺序仍为从右向左,第2个表达式i++的值为4,此时变量i并没有立即自增,,所以第1个表达式i++的值仍为4。最后再从左到右输出每个表达式i++的值:4,4。当输出函数执行完成之后,变量i执行i++操作,一共执行了2次,i的值为6。

4、自增(自减)运算符在循环结构中的应用

在循环语句while,do while和for中都有类似“i++;”或“i--;”这样由变量和自增自减运算符构成的赋值语句充当使循环趋于结束的语句,目的是为了避免程序出现死循环。

例#include

Void main()

{int s=0,i;

for(i=1;i<=20;i++)

s=s+i;

printf("%d\n",s); }

分析:当循环变量i=21时,条件不成立,循环结束。

在循环表达式中出现的自增自减运算符可看做独立的语句,++i 和i++最终都使得循环变量i的值自增,所以没有分别,等价于i=i+1。

三、结束语

自增、自减运算符是 C 程序设计语言中特有的,在编程过程中经常用到,但对于初学者而言,往往感到难以理解这两个运算符的运算实质,因此使用自增自减运算符时要特别小心,仔细考虑,否则会得到莫名其妙的结果,对于初学者在学习中应该多分析,同时也应多上机练习。希望通过对此所作的探讨,能够使初学者正确理解自增、自减运算符的作用和意义。

参考文献:

[1] 谭浩强.C程序设计[M].3版.北京:清华大学出版社,2005.

[2] 梁海英.C语言程序设计.清华大学出版社.2013

[3] 朱承学.C语言程序设计教程 [M].中国水利水电出版社.2004.

摘 要:自增、自减运算符是 C 程序设计语言中特有的,在编程过程中经常用到。本文根据自增(自减)运算符的特点, 浅谈自增(自减)运算符在VC++6.0编译器的应用,以期为初学者学习和使用自增(自减)运算符提供一些帮助。

关键词:C语言;自增(自减)运算符;表达式

中图分类号:G642 文献标识码:B 文章编号:1002-7661(2014)21-009-01

C语言功能强大,使用灵活,是初学者的很好的入门语言。而自增(自减)是C语言中比较有特色的运算符,在编程中合理使用可以节省代码,提高效率;但是如果使用不当,则极易造成错误。本文根据自增(自减)运算符的特点, 浅谈自增(自减)运算符在VC++6.0编译器的应用,以期为初学者学习和使用自增(自减)运算符提供一些帮助。

一、自增(自减)运算符的含义及使用形式

1、自增自减运算符的含义

C语言的自增和自减运算符分别是:++,--。作用是使变量的值加1或减1,它们能操作的对象只能是变量,常量不能进行自增(自减)运算。如7++相当于7=7+1,和赋值表达式的要求不相符。特别要注意的是在C语言中,数组名和函数名都属于常量,因此不能进行自增(自减)运算。表达式也不能进行自增(自减)运算。如(a+b)--,等价于a+b=a+b-1,不符合赋值表达式的要求。自增(自减)运算符具有对运算量重新赋值的功能,故不能对无存储空间的对象进行重新赋值。

2、自增(自减)运算符的使用形式

自增(自减)运算符作用于变量之前称为前缀运算(++i或--i),运算符作用于变量之后称为后缀运算(i++或i--)。前缀运算规则为:“先变后用”,即,加(减)号在前,先加(减)后用;运算结果:变量的值相应增加1(减少1)。后缀运算规则为:“先用后变”,即,加(减)号在后,先用后加(减);运算结果:变量的值相应增加1(减少1)。

二、自增(自减)运算符的灵活运用

“++、--”运算符在 C 语言程序中的运用非常广,也非常灵活,现通过例子说明。

1、自增(自减)运算符在表达式中的应用

例 #include

void main()

{int i=3,j=3,p,q;

p=++i;①

q=j++;②

printf("%d,%d,%d,%d\n",p,q,i,j);}

运行程序,输出结果为:4,3,4,4

分析:①是前缀,“先变后用”。即先执行i=i+1,在执行p=i。因此i和p的值都是4。②是后缀,“先用后变”。即先执行q=j,在执行j=j+1。因此q的值为3,j的值为4。

2、自增(自减)运算符的混合应用

设i的初值为4,求表达式p=(i++)+(i++)+(i++);自增运算作为后缀式,其运算优先级低于求和运算。相当于先执行p=i+i+i,在执行i++,i++,i++。因此p的值为12,i的值为7。

而表达式p=(++i)+(++i)+(++i);自增运算作为前缀式,其运算优先级高于求和运算。故先按照“自右至左”的结合性进行两次自增运算即++i,++i,i的值变为6,获得满足第一个求和运算符两侧的操作数要求进行6+6求和运算,然后将和值(12)与变量i的第三次自增值(i=7)进行第二次求和运算(12+7)即p=((++i)+(++i))+(++i)=(6+6)+7=19,最后i的值为7。

关于自增(自减)运算符的在混合应用中的规则我们可以理解为,若作前缀形式,其运算优先级高于其它算术运算,即先按照“从右至左”的结合性进行自增(自减)运算,再进行其它运算;若为后缀形式,其运算优先级低于其它算术运算,即先进行其它算术运算,再按照“从右至左”的结合性进行自增(自减)运算。

3、自增(自减)运算符在函数调用中的应用

在调用函数时,对函数参数的求值顺序是自右至左。

例如:i=4; printf("%d,%d",++i,++i);

上面printf函数中遵循从右至左的求值顺序,先求出第2个表达式 ++i 的值 5,然后求第1个表达式++i的值6,最后再从左到右输出每个表达式++i的值:6,5。

i=4; printf("%d,%d",i++,i++);

上面输出函数执行顺序仍为从右向左,第2个表达式i++的值为4,此时变量i并没有立即自增,,所以第1个表达式i++的值仍为4。最后再从左到右输出每个表达式i++的值:4,4。当输出函数执行完成之后,变量i执行i++操作,一共执行了2次,i的值为6。

4、自增(自减)运算符在循环结构中的应用

在循环语句while,do while和for中都有类似“i++;”或“i--;”这样由变量和自增自减运算符构成的赋值语句充当使循环趋于结束的语句,目的是为了避免程序出现死循环。

例#include

Void main()

{int s=0,i;

for(i=1;i<=20;i++)

s=s+i;

printf("%d\n",s); }

分析:当循环变量i=21时,条件不成立,循环结束。

在循环表达式中出现的自增自减运算符可看做独立的语句,++i 和i++最终都使得循环变量i的值自增,所以没有分别,等价于i=i+1。

三、结束语

自增、自减运算符是 C 程序设计语言中特有的,在编程过程中经常用到,但对于初学者而言,往往感到难以理解这两个运算符的运算实质,因此使用自增自减运算符时要特别小心,仔细考虑,否则会得到莫名其妙的结果,对于初学者在学习中应该多分析,同时也应多上机练习。希望通过对此所作的探讨,能够使初学者正确理解自增、自减运算符的作用和意义。

参考文献:

[1] 谭浩强.C程序设计[M].3版.北京:清华大学出版社,2005.

[2] 梁海英.C语言程序设计.清华大学出版社.2013

[3] 朱承学.C语言程序设计教程 [M].中国水利水电出版社.2004.

C语言中的函数与指针 篇3

随着计算机技术的飞速发展及应用领域的扩大, 熟练掌握一门语言已变的尤为关键。C语言这门课程在计算机的基础教学中一直占有比较重要的地位, 然而要想突破C语言的学习, 对函数和指针的掌握是非常重要的, 本文将具体针对函数和指针的关系做详尽的介绍。

一、函数的有关概念

为了使程序的编写更加清晰、直观且易于修改, C语言中引用了函数。所谓函数, 就是一个程序模块, 该模块用来完成一个特定的程序功能。引用一个函数时, 需要包括对函数的定义、声明, 继而调用。在掌握函数相关概念的同时, 有以下几点需要注意:

(1) 调用函数和被调用函数

由上例可以看出, 函数A在执行的过程中包括了对函数B的调用, 则函数A称为调用函数 (调用函数B) , 而函数B被函数A调用, 称为被调用函数。

(2) 实参和形参

调用函数中定义的变量是实参, 被调用函数中定义的变量是形参。如上例, 函数A中的变量a是实参, 函数B中的变量b是形参。

(3) 实参变量和形参变量之间的独立性

实参变量和形参变量之间只存在值的传递过程, 实参变量的存储空间在调用函数中分配, 而形参变量的存储空间在被调用函数中分配, 被调用函数执行完毕后, 其所分配的存储空间被释放, 即形参变量的存储空间被释放, 它不会返回值给实参变量, 也不会参与调用函数的继续执行。例如 (实现两个数的交换) :

显然, 函数main是调用函数 (调用函数swap) , 函数swap是被调用函数。main函数中的a, b由main函数分配存储空间, 而swap函数中的a, b由swap函数分配存储空间。main函数执行到swap函数时, 调用swap函数, swap函数为其变量分配存储空间, 然后实现了swap函数中变量a, b的值交换, 执行完毕后即释放其分配变量的存储空间。继而, main函数继续执行, 但其变量a, b没有做任何改变, 即main函数不能实现a, b的交换。由上例可以看出, 若单纯的使用变量, 则被调用函数无法改变调用函数中的变量值, 即swap函数无法实现main函数中变量a, b的交换。

二、指针的有关概念

指针是C语言中功能最强大, 使用最广泛的一种数据类型, 主要用于描述存储单元的地址。通过使用指针, 可以在函数中进行传址调用。

(1) 指针变量的定义

定义指针变量的一般形式:类型标识符*变量名;其中, 变量名前的符号“*”表示将要定义的变量, 类型说明符表示该指针变量所指向数据的类型。例如:int*p1;char*p2;float*p3;

(2) 指针变量的引用

&为取地址运算符, 其一般形式为:&变量名, 例如:

int x=3, *p;p=&x;指针变量p指向变量x。

在使用x的值时, 可以直接使用x, 也可以用*p来代替使用x。此外, 指针变量一定是和它所对应的变量相互引用, 即指针变量在使用时一定要有明确的指向, 必须赋予具体的值, 否则将可能导致错误。

三、指针与函数的关系

在函数的编写过程中, 若单纯的只用变量参数, 则无法实现被调用函数改变调用函数中变量值的目的。而为了实现这一目的, 就需要函数和指针之间的结合使用。

(1) 引用指针, 可以实现调用函数和被调用函数中的指针变量共同指向调用函数中的存储单元, 从而实现被调用函数改变调用函数中变量值的目的。例如:

由上例可以看出, 在调用函数 (main函数) 中定义了变量a和指针变量p1, 被调用函数 (change函数) 中定义了指针变量p2。程序首先从main函数开始执行, 分配变量a和指针变量p1的存储单元, 此时指针变量p1指向变量a (p1=&a) 。当程序执行到change函数时, 程序跳转到change函数执行其函数体, change函数为其指针变量p2分配存储单元, 同时p2也得到了p1传过来的值 (变量a的地址) , 此时p2也指向了调用函数中的变量a, 即实现了p1和p2共同指向了调用函数中的存储单元 (变量a的存储单元) , change函数执行其函数体 (*p2=3) , 即使a的值变为3。change函数执行完毕后, 释放其变量的存储空间, 转而继续执行main函数, 此时a的值已经发生改变 (由2变为3) , 实现了被调用函数改变调用函数中变量值的目的。

(2) 调用函数和被调用函数中实参和形参之间的关系图

被调用函数执行完毕后, 释放它所分配的存储单元, 而调用函数分配的存储单元仍继续使用。此外, 只有当调用函数中传指针值 (即实参是指针值) , 而被调用函数中引用变量 (即形参收到指针值后, 在函数体内引用变量值) , 才能达到改变的目的。

例如, 实现变量a和b的交换, 程序如下:

例1虽然传的是指针值, 但在函数体的执行过程中引用的仍然是指针值 (引用x和y) , 所以不能实现a和b的交换;例2程序传指针值后, 引用变量 (*x和*y, 即a和b) , 所以能实现a和b的交换。

四、结束语

在以后的编程过程中, 若遇到想通过被调用函数改变调用函数中变量值的目的, 则可以把该变量的地址值传给被调用函数, 从而达到改变的目的。鉴于文章篇幅及个人能力有限, 本文肯定还存在许多不足之处, 仅供大家学习和参考。

参考文献

[1]谭浩强.C程序设计[M].二版.清华大学出版社, 2004.

[2]杜友福.C语言程序设计[M].二版.科学出版社, 2007.

C语言指针探究 篇4

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语言指针应用 篇5

一、理解指针

在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.

C语言的指针解析 篇6

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语言的指针学习法 篇7

关键词:指针,数组,地址,变量

凡是学习过c语言的都知道指针是c的灵魂, 它极大的丰富了c语言的功能。下面这部分内容就我个人认识做如下阐述。

1 指针的出现

我想有很多初学者学习到指针都感觉很难, 下面我就以自己的想法来解释下指针这个特殊的数据类型。基本类型变量大家可能并不难理解, 因为基本类型变量其内部存储了同类型的常量, 事实上指针也是变量, 不过呢, 这个变量和基本变量有点不一样, 不同点就在于基本类型变量内部存储了同类型的常量, 而指针变量内部存储的则是“同类型变量的首地址” (所指向的变量的地址) 。可以给你形象的来描述一下:

int a;/*声明一个基本整形的变量*/

此时, 编译器已经给a分配了连续4个字节的内存空间 (VC++6.0) , 结构如图1。

内存地址是线性编码的, 我们可以很容易的看出a的首地址就是他第一个单元的地址1001。

int*Pointer=&a;/*声明一个指向a的指针Pointer*/

编译器也同样给指针变量Pointer分配相应字节数的内存空间, 如图2

该内存空间里存放1001, 即为变量a的地址。

在程序设计中, 如果存在语句:a=10;直接给a赋值, 我们称为直接访问。

如果使用语句:*Pointer=10;即通过指针变量来赋值, 前面的*是间接运算符号, 意思是求Pointer内部存储地址所标识的内存单元, 也就是a。此时, 该赋值是通过间接访问来实现的。如图3

以上就是指针实现的基本解释, 很多优秀的程序员都说指针是C语言中的精华, 的确如此, 很多优秀的程序员写程序都非常依赖指针, 因为它很方便, 实际上指针所访问的对象是没有限制的, 他可以指向任何类型的变量, 前提是只要我们知道内存地址。因此指针也并不安全, 在开发网络程序的时候, 尽量要少使用指针。

2 指针在数组中的使用

简单的来解释下数组, 数组是“同类型变量的有限集合”。数组在内存中占用连续的内存单元 (地址连续) , 来存储数组中的每一个元素。数组是预先分配好指定长度的内存单元, 供数组元素使用。它并不支持动态内存分配。

下面以字符型数组为例来分析字符指针和一维数组之间的关系。数组名其实就是这一组内存单元的首单元, 它的地址就是整个数组的入口地址;数组名是一个指针, 它的基类型为基本数据类型, 不过在具体操作的时候不允许给数组名重新赋值, 可以把数组名理解为cons Pointer (指针常量) 。在程序中可以这样操作:

即同类型的指针, 完全可以胜任数组名的任务。一点问题没有而且可以运行的很好。当然, 我们可以进一步把代码这样来写:

改成

下面以基本整型二维数组为例来分析指针和二维数组之间的关系。二维数组名也代表二维数组的首地址, 也是一个指针常量, 只是其基类型为数组类型, 称为行指针 (a指向第0行, a+1指向第一行) 。可以把二维数组看做一个特殊的一维数组, 只是每个元素又是一个一维数组而已。在程序中可以这样操作:

/*把二维数组看做一维数组时, 每个数组元素a[0]、a[1]、a[2]又包含一个一维数组, 该一维数组又包含4个元素, 这样a[0]、a[1]、a[2]即成为相应的数组名, 也成为一个指针常量, 其基类型为基本整形;所以可以把a[0]、a[1]、a[2]分别赋给指针数组的相应元素*/

p=a;/*p为行指针, 其基类型为数组类型*/

3 总结

指针本身与指针所指向的变量不是一个单元, 一定要弄清楚指针变量的基类型。一个指针ptrold加上或减去一个整数n后, 结果是一个新的指针ptrnew, ptrnew的类型和ptrold的类型相同, ptrnew所指向的类型和ptrold所指向的类型也相同。

参考文献

[1]C语言初学者入门讲座:<http://www.gshu.cn/detail/0/337.htm>

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

关键词: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.

上一篇:模型自适应计算下一篇:循环经济产业园

本站热搜