数组越界问题、指针初入门

主要内容:数组越界问题和指针初入门例子分析

一、 数组越界问题

  1. 例子思考
int main()
{
	int i;
	int arr[10];
	for(i=0;i<=10;i++)
	{
              arr[i] = 0;
	          printf("%d\n",i);
	}
	return 0;
}

问题:当运行上述代码时,会出现什么问题?为什么会这样?

 为解决以上问题,我们首先得明白当定义一个函数时,函数中各个量的空间分配符合栈(后进先出)的原则,如果一个量被先定义,那么系统便先给它分配存储空间。而在数组中,0号下标地址值永远小于1号下标地址值。因此,对于上述问题,我们可以画出它的内存空间示意图,分析运行代码会出现什么结果。具体图如下所示:


 根据上图所示,程序从主函数开始往下执行,当int i;时,系统首先为i分配四个字节的空间,接着int arr[10];时,定义了一个长度为10的数组,因为在数组中,0号下标地址值永远小于1号下标地址值,同时栈的定义就是栈底地址大。便可知到上图(左)(图中两红线之间表示为数组所占空间)便为定义后,i与数组arr在内存中分配图。接着执行:for(i=0;i<=10;i++){arr[i] = 0; printf("%d\n",i);}。当i<10时,数组下标0-9分别对应的元素被赋值为0。i=10时数组满溢,会发生越界情况。在数组越界情况中,数组会默认牵涉其邻近元素,在此例子中即为i,因此当i=10时,系统会将i所对应的值赋为0。

  1. 结论
     此段代码运行时会产生死循环。原因是:因为数组越界,当i=10时,系统将i所对应的值赋为0,此时i=0i<=10系统又会进入新一轮循环。以此类推,系统陷入死循环。

  2. 解决办法
     i.编译器:Visual Studio 2012针对于上述问题会产生崩溃现象,具体实现过程如上图(右),VS12会在数组arr与变量i中间进行隔离,避免数组越界影响到i,同时在数组arr与变量i中间申请两个内存空间,分别放在两颗“炸弹”,数组一旦越界,触碰到炸弹,系统中断,提出警告。
     ii.人力控制:牢记数组最大下标值=数组长度-1,代码仔细书写,避免越界问题产生。

二、 指针初入门

  1. 概念介绍
    符号& :表示取地址。//eg: &a表示取a 的地址。
    符号* :可以表示乘法、定义一个指针变量、对变量解引用。//eg: 34、intp(定义一个指针变量p)、*p(对p解引用)
     首先我们得知道指针==地址 ,通过以下介绍,我们来理解指针为什么相当于地址。
    在这里插入图片描述

  2. 例子思考
    其中&a=1000,&b=2000,&p=3000,观察此代码,分析每一步都做了什么!

int main()
{
	int a = 10;
	int b = 20;
	int *p = &a;
	*p = 100;  
	p = &b;                     
	*p = 200;                       
	int **pp = &p;
	*pp = &a;                  
	**pp = 1000;                
	*pp = &b;                       
	**pp = 2000;               

	return 0;
}

 对上段代码,我们画图理解:在这里插入图片描述

 (1)定义一个整形变量a,并将10赋值给它;
 (2)定义一个整形变量b,并将20赋值给它;
 (3)定义一个整形指针变量p保存变量a的地址,此时执行上图中的第(1) 步,p指向a;
 (4)*p = 100;对p解一次引用,此时p指向a,即a=100;
 (5)指针变量p保存变量b的地址,此时执行上图中的第(2) 步,p指向b;
 (6)*p = 200;对p解一次引用,此时p指向b,即b=200;
 (7)定义一个整形二级指针变量pp保存指针变量p的地址;
 (8)对pp解一次引用,也就是执行上图中的第(3) 步,pp指向p,此时p中保存的是a的地址,即p=&a;
 (9)对pp解两次引用,也就是执行上图中的第(3) 步,再执行第(1) 步,pp指向p,此时pp指向a的值, **pp = 1000,也就是将a的值置为1000;
 (10)对pp解一次引用,也就是执行上图中的第(3) 步,pp指向p,此时将b的地址赋值给p,p中保存的是b的地址,即p=&b;
 (11)对pp解两次引用,也就是执行上图中的第(3) 步,再执行第(2) 步,pp指向p,此时pp指向b的值, **pp = 2000,也就是将b的值置为2000;
因此,此代码每一步都做了什么展示如下:

int main()
{
	int a = 10;(1)
	int b = 20;(2)
	int *p = &a;(3)
	*p = 100;(4)                             //a = 100;
	p = &b;(5)
	*p = 200;(6)                             //b = 200;
	int **pp = &p;(7)
	*pp = &a; (8)                            //p = &a;
	**pp = 1000; (9)                         //a = 1000;
	*pp = &b;(10)                             //p = &b;
	**pp = 2000;(11)                         //b = 2000;

	return 0;
}

猜你喜欢

转载自blog.csdn.net/du_lijun/article/details/83083317
今日推荐