数组及指针

一、数组

1.数组的定义

    数组在定义时,有数据类型,例:  定义一个整型数组:int arr[10],且其中的10表示的是数组的长度。

2.数组的使用

    数组在使用时,无数据类型,例:  arr[3]=10,其中3表示的是下标。

3.在数组中,还有一个特别重要的概念-初始化。

    若完全不初始化,则在数组使用时,各位置上的值将为计算机随机赋值(例:int brr[10]//计算机将会为数组赋随机值);

    若只初始化一部分,则优先紧着前面的位置存放。即聚合类型若只初始化一部分,则剩余部分为0(例:int crr[10]={1,2,3,4}即为int crr[10]={1,2,3,4,0,0,0,0,0,0});

    在此,我将给出一个易出错的地方,即:

        int drr[2] = {1};
	printf("%d\n",drr[0]/drr[1]);

     在以上这段代码实现过程中,编译器将会出现报错,其原因为:drr[0]=1,drr[1]=0,而0不能做分母。

4.写一个数组打印函数

扫描二维码关注公众号,回复: 3579147 查看本文章
#include <stdio.h>
void Show(int arr[10])
{
	for(int i=0;i<10;i++)
	{
		printf("%d ",arr[i]);
	}
	printf("\n");
}
int main()
{
	int arr[] = {1,2,3,4,5,6,7,8,9,10};
	
	Show(arr);

	return 0;
}

     在以上代码循环部分,需注意一个问题‘i<10’比‘i<=9’要更好,那是因为在C中一般遵循“左闭右开”(即左边取等号,而右边不取)原则。

5.数组越界(非法访问内存,修改了别人的内存)问题的处理

     首先,在此需介绍一个问题,那就是局部变量的位置-栈。在此,我也将通过一段代码对数组越界问题进行分析,如下:

#include <stdio.h>
int main()
{
	int i;
	int arr[10];
	for(i=0;i<=10;i++)
	{
		printf("%d\n",i);
		arr[i] = 0;
	}
	return 0;
}

     以上代码为典型的栈处理数组越界打印问题,因为在循环过程,循环次数11超过数组长度10,即arr[10]越界修改了i的值,导致出现死循环。

    在此值得一提的是,VC6.0、DEV和Visual studio 2012的区别。

    VC6.0、DEV在数组存放时,无‘地雷’设置,是挨着存放的,且每次地址都一样,而Visual studio 2012不同,它会在两变量之间设置有两个‘地雷’防止越界,并且每次的地址都不同。对如下代码进行分析:

	int a;
	int b;
	int arr[10];
	printf("%d,%d,%d\n",&a,&b,&arr);

    在 VC6.0、DEV中,a与b地址间距为4,仅为b本身所占字节,b与数组arr地址间距则为40,仅为arr本身所占字节。

    在Visual studio 2012中,a与b地址间距为12,即两个‘地雷’所占字节+b本身所占字节(2*4+4),b与数组arr地址间距则为48,即两个‘地雷’所占字节+arr本身所占字节(2*4+10*4)。

    但Visual studio 2012对于处理越界问题也不是万能的,例如:

#include <stdio.h>
int main()
{
	int i;
	int arr[10];

	for(i=0;i<=10;i++)
	{
		printf("%d\n",i);
		if(i == 10)
		{
			i += 2;
		}
		arr[i] = 0;
	}
	return 0;
}

     在if语句中‘ i+=2’操作由于跨越了‘地雷’的设防,导致程序也将出现bug。

6.一维数组数组名arr在如下两种情况表示整个数组
    (1)在定义数组的同一个函数中,sizeof(arr)
    (2)在定义数组的同一个函数中,&arr+1

     其它情况数组名arr表示数组首元素的地址。如下代码实现:

#include <stdio.h>
int main()
{
	int arr[] = {1,2,3,4,5,6,7,8,9,10,11};

	printf("%d\n",sizeof(arr));//44
	printf("%d,%d\n",&arr,&arr+1);//arr与arr+1地址间隔为44
	return 0;
}

二、指针

    首先,需要了解一个概念,即‘指针==地址’。(int *p//整型的指针变量p;int x=10//整型变量存放整型值;int *p=100//整型地址变量存放整型地址值)

    (在此,穿插一个关于左右值的问题。例:a=50//a做左值;b=a//a做右值。)

    我将通过如下代码对有关指针进行理解:

	int a = 10;
	int b = 20;
	int *p = &a;//即p保存了a的地址
	*p = 100;//a = 100;(跳到了它所保存的地址即a,p引用了a)     解引用(间接引用符 *)
	p = &b;
	*p = 200; // b = 200
	int **pp = &p;
	*pp = &a;//p = &a;
	**pp = 1000;//a = 1000;
	*pp = &b;//p = &b;
	**pp = 2000;//b = 2000;

    在以上代码中,应用到了解引用(间接引用符 *),那是因为指针变量比其它变量多了一个解引用(指针变量和其它变量一样,都是一个变量而已)。

    且通过以上代码可知:a-整型变量   、&a-整型地址变量  、 p-int * 、   &p-int **(二级指针)。(取一次地址,多一个*)

    注:有关‘*' 的有关用法:

    1.乘法(双目运算符   例:3*4)

    2.指针变量(在定义时体现,例:int *p=&a)

    3.解引用(也即间接引用符 *,在使用时体现,无数据类型,例:*p=100)

    有关指针的字节占用问题:在X86(32位平台)占4字节;在X64(64位平台)占8字节。

    有关赋值成立的条件:(1)数据类型一样;(2)窄的赋值给宽的,例:char可以赋值给int。

猜你喜欢

转载自blog.csdn.net/Aspiration_1314/article/details/79511596