用栈是无法产生垃圾数据的(想一想计算机原理).但是在使用堆的过程中很有可能产生的(多是一些难以回收的内存碎片,编译时又不会报错,或是其中的死循环,漏洞),程序越小,产生垃圾数据的可能性就越小.现在,有些软件甚至故意在内存和硬盘中留下一些无用数据,这是人为因素.
创新互联服务项目包括爱民网站建设、爱民网站制作、爱民网页制作以及爱民网络营销策划等。多年来,我们专注于互联网行业,利用自身积累的技术优势、行业经验、深度合作伙伴关系等,向广大中小型企业、政府机构等提供互联网行业的解决方案,爱民网站推广取得了明显的社会效益与经济效益。目前,我们服务的客户以成都为中心已经辐射到爱民省份的部分城市,未来相信会继续扩大服务区域并继续获得客户的支持与信任!
由于当初这些空间是向系统申请得到的,最后应该由程序返还,一切都合乎规则,对于内存来说,当系统结束工作时,会强制回收内存,保证安全的关机;对于硬盘来说,由于申请是合法的(对系统来说),所以系统无法处理,可以用杀毒软件.
在所有函数体之外定义的基本数据类型的变量会被默认初始化.在函数体内未初始化而直接使用一个变量(赋值,或以其他形式访问)会导致未定义的结果,既程序正常运行,或崩溃,或产生垃圾数据.
首先这个数组不是静态数组,因为你没有写static关键字!
所以这个数组是局部数组,进入函数时创建,函数结束时撤销。
这个程序编译时一般会有警告——你返回了一个已撤销的数组的起始地址。
打个比方:你在旅馆里开了5间房,并把第一间房的房号作为函数值。
函数结束时,退了房,但房号(即地址)还是在的,但那房间却不属于你的了。
如果没有新人入住,那么里面的内容就没变。一旦新人入住,那么里面的内容就会改变。
直接看第二个程序:
1) pArr = staticArr();
2) printf("%d\n", *(pArr + 1));
3) printf("%d\n", *(pArr + 2));
第1行:pArr得到了已撤销的数组的起始地址。
第2行:调用printf函数之前,首先通过*(pArr+1)获取了这个已撤销数组的第一个元素的值,由于房间还没新人入住,所以可以得到原来的值。接着,就把这个值传给printf函数,注意它是复制了一份再发给printf函数的。
注意:所有函数在调用时所给出的实际参数都将被复制给被调函数的形式参数的——即函数的形式参数都是复制品。
现在调用printf函数——新人入住了,那个数组的房间现在分配给printf函数去用了,其中内容被改变,但是printf函数输出的是复制品,不是原件,所以“看起来没变”。
第3行:再次通过*(pArr + 2)取值的时候,就取到了被前一个printf函数改变以后留下的垃圾值,而且这个printf函数将再次改变这些房间,留下不同的垃圾值。
用任何方法输出这个已经不属于你的数组的内容,都是毫无意义的,因为它都是前一个printf函数结束工作后留下的垃圾数据。
如果你在数组定义前加static关键字,结果就不同了。
static int a[5] = {...};
不信,你就试一试!
如果没有这一句,ch是一个未初始化的变量,可能输出任何数值,跟编译器相关。例如我用vs2008,ch对应的内存中值为-52. 所以绝大多编码规范要求定义的变量必须初始化,防止异常的情况出现。
加上这一句,当你输入一个数后,会按回车键,getchar就扑捉到你输入的换行字符。
你查查ASCII码。换行对应的ascll码就是10.