论文导读::也有人在教学中关注了内存的概念[5]。内存与数组。内存与函数参数。内存与变量的作用域和生成期。生成期是因为函数执行的时候才会调入内存。
关键词:内存,数组,参数,作用域,生成期
1 引言
C语言一般作为计算机及相关专业的第一门语言,它是后续计算机课程的基础,学生对它的掌握程度直接影响到后续课程的学习。由于C语言本身的语法规则灵活,程序书写随意性大,数据类型多样,使得学生普遍感觉该课程难度较大。为使学生掌握C语言程序设计的思想和方法,培养学生分析问题和解决问题的能力,教师在实际授课中不断改进教学方法,取得了很多可以借鉴的研究成果。如有人对整门课程的教学方法进行探讨[1,2],有人对C语言的重点和难点[3,4]进行教学过程探讨,也有人在教学中关注了内存的概念[5]。内存在计算机工作过程中扮演着存放正在运行的程序和数据的角色,具有非常重要的作用,如果掌握了数据在内存中的布局,就能更透彻地理解程序的执行情况,所以在教学中适当引入内存的概念显得非常必要。
2 有关内存概念的应用
2.1 内存与数组
程序中的变量需要占用内存空间,内存空间有地址。不同数据类型的变量,可能占用不同的内存大小数学小论文,对于简单数据类型char,int,float,double,我们知道它们分别会占用1、2、4、8个字节,对于struct类型,我们也能用sizeof运算符去计算出它在内存中所占的字节数。但如果是某种类型的数组,然后再加上指针运算,有时学生就会感到迷惑,如程序段:
float a[10];
float *p=a;
p++;/*p的值究竟是加1还是加4*/
以上程序段中,a是数组名,它是一个常量,表示数组的起始地址,指针p指向这个起始地址,p++是从这个起始地址向后移动到下一个元素,所以p会往后移4个字节,而不是移动一个字节。又如
float *pa=(float*)malloc(sizeof(float)*10);pa是一个指针变量,它指向float类型,malloc申请的一段空间本来是void类型的,应该以字节为单位来表示,但用(float*)把这段空间强制转换为float类型(注:malloc返回的空间一般都需要作强制类型转换),它也能起到和数组相同的作用,唯一不同的是a是数组名,是常量,在程序任何位置都不可变化,pa是指针变量,程序中可以改变它的值。所以用固定形式的数组定义的空间和用动态形式申请的空间从内存的角度看,其实没有什么区别,它们都是一段连续的空间,至于这段空间怎样存放数据以及指针在这段空间上怎样动作,则是由数据类型决定的。另外在教学中需要强调的是,既然它们只是一段连续的空间,程序要访问这段空间就不能出现越界行为,如果出现越界行为,则说明访问到外面去了,这将会发生意料不到的甚至灾难性的后果。另外我们使用malloc函数动态申请内存时,始终要注意动态内存是在堆中分配,自己申请内存用完后必须自己回收数学小论文,如果没有回收,会造成内存泄漏。
2.2 内存与函数参数
函数是C语言程序的基本结构单位,在函数调用中一般会有一个参数传递的过程,参数传递分为值传递和地址传递。当参数为非指针类型时,是值传递,例如:有函数原型void fun(int x,int y),这个函数在程序中被调用的时候,设传入的参数为a=3,b=4,则不管fun函数中对x和y做了什么事情,它总是与传入的参数a、b本身没有任何关系,因为x、y与a、b位于不同的内存空间。而如果函数参数是指针类型时,对函数中参数的改变有可能会影响传入参数的值,如有:
void Swap(int*x,int *y)
{
int t;
t=*x;
*x=*y;
*y=t;
}
void main()
{
inta=3,b=4;
Swap1(&a , &b);
printf(“%d %d”,a,b);
}
程序调用前,设a和b在内存中的位置如图1所示,调用Swap函数时,是把a和b的地址作参数进行传递,参数传递形式如图2,所以Swap函数执行时,x的值为1000,y的值是2000,x指向的值是a,b指向的值是b,在函数内部交换了x指向的值和y指向的值,所以这段函数实际上是交换了a和b的值。若把Swap函数改写为如下形式:
void Swap(int*x,int *y)
{
int *t;
t=x;
x=y;
y=t;
}
这时仍然按main()中的方式调用,这时的参数传递形式仍为图2,但这时Swap函数中是交换x和y本身的值,x和y本身的值无论怎么变化,只要地址里面的值没有变化,对a和b就不会造成任何影响。其实在c语言中使用指针作参数,要么是为了提高程序的执行效率,不必拷贝一大块数据到调用函数中,要么是为了通过参数带回值,因为每个函数最多返回一个值,如果有多个不同的值要返回,就可以考虑用指针类型的参数带回。
图1 a和b在内存中的位置
图2 调用Swap函数时的参数传递形式
2.3 内存与变量的作用域和生成期
作用域指变量在程序中有效的空间范围,而生存期指变量在内存中的存在时间范围。如果某个变量在作用域之内同时又在生成期之内则可被访问数学小论文,其它情况则不能被访问。函数内变量(包括形式参数)的作用域是从定义的位置开始到函数结束,函数外定义的变量作用域是从定义位置开始到本程序文件结束,这也解释了变量为什么必须先定义然后才能使用。生成期是因为函数执行的时候才会调入内存,这时才会在内存中分配函数内部的变量空间,当函数执行完后这些空间又自动收回,生成期这时也结束。在实际编程时,往往有很多初学者忽视了这两个概念,当他们编写返回指针的函数时,常常出现了返回局部自动变量地址的错误,如:
Node* CreateList()
{
Node head;
/*其它程序语句*/
return &head;
}
这段函数在调用的时候可能会出现错误,原因是函数调用结束后,函数内所有自动变量的生成期都结束,变量head的空间会被回收,这时原来变量head地址里面的内容变为无效。若要在函数中返回地址,我们一般考虑返回在堆中申请空间的地址。如把以上函数改为
Node* CreateList()
{
Node*head;
head=(Node*)malloc(sizeof(Node));
/*其它程序语句*/
return head;
}
则可保证返回的内容是有效的,但以后必须手动删除堆中的内存。
3 结束语
从内存的角度解释实际编程时出现的一些问题,让学生掌握一些较为本质的内容,在实际授课中取得了较好的效果,希望本文的思想能为计算机基础教育工作者提供一些借鉴。
参考文献
[1]李新霞.也谈C语言教学[J].计算机教育,2004.12:67-69
[2]陈仲民.关于C 语言教学方法和程序设计的探讨[J].计算机教育,2007.6:3-6
[3]徐洪智,张彬连.基于C语言的递归函数教学方法探讨[J].计算机教育,2008.2:57-58
[4]唐政.C语言中指针的灵活运用[J].上海电机学院学报,2005,8(2):63-66
[5]张仿.内存概念在C语言程序设计教学中的应用[J]. 黑龙江工程学院学报(自然科学版),2004,18(1):39-41
|