《标准C语言程序设计》上机报告实验四变量存储类型的理解和使用以及数组初步专业:通信工程班级:通信学号:U201姓名:完成日期:2011.5.11一、实验目的1.熟悉变量的各种存储类型的定义和申明2.理解各种存储类型变量的作用域和生存期;3.掌握局部变量和全局变量;4.掌握动态存储和静态存储;5.掌握一维数组和二维数组的定义、初始化和数组元素的引用;6.理解并掌握数组名和数组下标的含义;7.与数组有关的算法初步(排序)8.掌握C开发环境中调试、跟踪数组元素取值和元素空间地址的使用二、实验内容及要求1.上机调试跟踪复合语句中的同名变量,掌握理解复合语句中局部变量的作用域以及变量存储空间的生存期。
写出你对同名变量使用的深入理解。
2.上机运行下面程序,调试跟踪static变量a和其它存储类型变量b、c的取值变化,加深理解不同存储类型变量的作用域和生存期语法概念,并给出你对静态局部和自动变量这两种局部作用域存储类型的深入理解。
3.教材习题四的第三题,给出运行结果,单步跟踪了解调试器对函数内部auto和static两种局部变量x和y的附带初值的定义语句执行过程有何区别?进一步深入理解两种局部变量auto、static的区别。
4.理解符号常量的作用域。
5.调试课堂下面代码了解下标越界问题.#include <stdio.h>#include <stdlib.h>void main(){int i;int a[10];for(i=0;i<=10;i++,printf("%d\n",i))a[i]=i-1;printf("用于输入的循环执行完毕!\n");printf("i=%d\n",i);printf("开始执行输出循环...\n");for(i=0;i<10;i++)printf("a[%d]=%d\n",i,a[i]);system("pause");//暂停}结合栈内存分配策略给出你对本例的越界问题理解。
6.用交换法对10个整数升/降序排列输出(要求:外层循环变量代表的轮次号从0开始编号,分别给出冒泡法和沉底法两种实现)7.输入一组实数,按录入顺序保存进数组arr中,采用设标记的选择法对其排序,任意输入一数,直接在arr数组中将其按序插入相应位置。
(不允许使用其它数组来完成)注:源代码(附详细注释),且要求版式规范化;代码复杂一点的要给出数据描述和各函数模块的接口描述(原型说明语句)。
报告中要给出程序测试运行时输入的数据和输出的结果,最好是切图,特别注意:测试运行时要尝试多种输入以检验程序设计的完备性(即设计的程序能否正确响应用户随意输入的数据,不会产生错误的结果,不会出现异常,不会没有任何反应等)三、解答在C语言中,在不同的层次的作用域内可以同名变量,但其实质为不同变量实体;同一层次作用域内不能定义同名变量,即使数据类型不同也不行。
在作用域层次相互嵌套的情况下,内层同名变量将对外层同名变量产生屏蔽,亦即:执行内层作用域语句时,使用的同名变量为内层定义的同名实体,屏蔽外层实体。
通过运行及跟踪该程序的运行过程,我发现自动变量的内存是动态分配的,每次进入函数或复合语句都要重新分配内存并执行初始化。
因此,不管何时进入函数或复合语句,自动变量类型数据的初始状态都是一样的。
而静态局部变量的内存是全局存在,即分配一次内存后只有在整个程序运行完毕后才释放它,因此初始化工作只执行一次,若不初始化,则系统将保证其初始值为0。
auto 变量是用堆栈方式占用储存器空间,因此,当执行此区段是,系统会立即为这个变量分配存储器空间,而程序执行完后,这个堆栈立即被系统收回。
auto 变量是指在函数内部定义使用的变量。
它只是允许在定义它的函数内部使用它。
在函数外的其他任何地方都不能使用的变量。
auto 变量是局部变量,即它的区域性是在定义它的函数内部有效。
当然这说明auto 变量也没有链接性,因为它也不允许其他的文件访问它。
由于auto 变量在定义他的函数的外面的任何地方都是不可见的,所以C允许在这个函数外的其他地方或者是其他的函数内部定义同名的变量,它们之间不会发生冲突的,因为它们都有自己的区域性,而且它没有链接性,即不允许其他的文件访问它的。
计算机在执行这个函数的时候,创建并为它分配内存,当函数执行完毕返回后,auto 变量就会被销毁。
static局部变量在所处模块在初次运行时进行初始化工作, 且只操作一次。
对于局部静态变量, 如果不赋初值, 编译器会自动赋初值0或空字符, 而auto类型的初值是不确定的。
static局部变量在两次函数调用时, 在第二次调用进入时,能保持第一次调用退出时的值。
4、符号常量的作用域是从定义符号常量的地方开始到包含这个#define命令(作用于该符号常量)的文件末尾或者遇到#undef命令(作用于该符号常量)为止。
经过调试可以发现,对于循环for(i=0;i<=10;i++,printf("%d\n",i)) a[i]=i-1; ,当i=10时,a[i]下标越界,a【10】被赋予未知的内存中的某个值,i值也被强行改变。
由于a[]是auto型变量,在内存中储存在栈内,a[9]比a[10]先储存,故a[10]用了a[9]的值,i值在这里也被强行改为9,导致i一直满足i 10成立,故该循环陷入死循环:6、冒泡排序法#include <stdio.h>void main(){int i,j,b;printf("Please input the 10 dates:\n");for(i=0;i<=9;i++){scanf("%d",&a[i]);}for(i=0;i<=8;i++){for(j=0;j<=9-i;j++){if(a[j]>=a[j+1]){b=a[j];a[j]=a[j+1];a[j+1]=b;}}}for(i=0;i<=9;i++){printf("%d\t",a[i]);}getch();}沉底排序法#include <stdio.h>void main(){int i,j,b;printf("Please input the 10 dates:\n");for(i=0;i<=9;i++){scanf("%d",&a[i]);}for(i=0;i<=8;i++){for(j=9;j>=i;j--){if(a[j]<=a[j-1]){b=a[j];a[j]=a[j-1];a[j-1]=b;}}}for(i=0;i<=9;i++){printf("%d\t",a[i]);}}7、代码:#include <stdio.h>#define N 5void main(){int arr[N];int n,i,j,b;for(i=0;i<=N-1;i++){scanf("%d",&arr[i]);}for(i=0;i<=N-2;i++){n=i;for(j=i+1;j<=N-1;j++){if(arr[j]<=arr[n]){n=j;}}if(n!=i){b=arr[i];arr[i]=arr[n];arr[n]=b;}}for(i=0;i<=N-1;i++){printf("%d\t",arr[i]);}int c[N+1];int x,z,k;printf("请输入所要插进的数:");scanf("%d",&x);for(i=0;i<=N-2;i++){if(arr[i]<=x&&arr[i+1]>x){c[N]=arr[N-1];for(k=N-1;k>=i+2;k--){arr[k]=arr[k-1];}arr[i+1]=x;}}if(arr[N-1]<=x){c[N]=x;}if(arr[0]>x){c[N]=arr[N-1];for(k=N-1;k>=1;k--){arr[k]=arr[k-1];}arr[0]=x;}for(i=0;i<=N-1;i++){c[i]=arr[i];}for(i=0;i<=N;i++){printf("%d\t",c[i]);}}四、上机中的感受、困惑及教学建议1、通过此次上机操作,我知道了到不同的数据类型有着不同的存储空间及作用域、寿命,即使是定义的位置不同,也可能使得出的结果完全不一样,因此在今后C语言的学习中,我将特别注意对数据类型的把握。
2、对于不同数据在内存中储存的位置,我目前仍不大清楚,比如auto类数据与statics类数据的具体在内存中储存位置的区别。
3、在上机操作过程中,我遇到了许多麻烦,具体包括:(1)不能熟练进行调试,甚至不知道调试可以用来做什么;(2)不知道“冒泡法”与“沉底法”排序的区别,后来与同学讨论后知道了他们之间的区别;(3)在写循环代码时,经常犯范围限制不准的毛病,导致程序运行时经常出现错误,因此同时浪费了大部分时间用在查找错误上,今后应尽量避免此类错误;(4)在做第(7)题时,不懂得怎样编写代码来实现向一个数组空间输入未知个数的数,同时如何不借用其他数组,就可实现在上述数组按序插入一个新输入的数。