说明
在C语言程序的编写中,涉及到数组。一般情况我们都是利用数组的下标对数组中的元素进行操作。
如: 一维数组:a[1]=51 二维数组:a[1][1]=51
当深入分析,会发现数组和指针之间是有一定的关系的。很多地方很绕,导致很难去理解。
我结合程序,写出我自己的看法。大家来一起研究。
内容
1. 整形(int)
首先从整形开始。我们定义一个整形变量,并且读取他的结果和地址。
int a = 10;
printf("整形a的值:%d\n", a);
printf("整形a的地址:%p\n", &a);
printf("整形a的值:%d\n", *(&a));
结果:
整形a的值:10
整形a的地址:007DF798
整形a的值:10
这很好理解,甚至我在第三句做了复杂操作:首先取 a的地址,然后对该地址进行 解引用,同样可以得到a的值。
注意: 此时的变量名仅仅是一个int类型的变量。
其结构如下图:
2.一维数组
我们开始讨论一维数组,char str[5]={"ABCD"};
首先先确定一位数组在内存中事怎么存储的。其结构图如下:
注意: 与整形不同,此时的变量名是一个指针,指向的是数组首元素的地址。
深入探讨: 这个str其实和真正的指针变量是稍有不同的。
一个指针变量:int * p = &a
其储存结构如下:
不同点:
- 对于指针变量,指针p有自己的内存地址,在其地址下 存放 了所指向 地址。
- 对于数组名,他自己的内存地址就是第一个元素的地址,对应的值也是一个元素的地址。
进行代码分析:
printf("--------------char[]------------\n");
char str[5] = { "ABCD" };
printf("数组的值:%s\n",str);
//partA
printf("--------------PartA------------\n");
printf("数组名str:%p\n", str);
printf("数组名str取址:%p\n", &str);
printf("数组名str取值:%c\n", *str);
printf("数组名str取值:%s\n", *(&str));
printf("--------------PartB------------\n");
printf("数组名str[1]取址:%p\n", str+1);
printf("数组名str[1]取址:%p\n", &str[1]);
printf("数组名str[1]的值:%c\n", str[1]);
printf("数组名str[1]的值:%c\n", *(str + 1));
结果:
--------------char[]------------
数组的值:ABCD
--------------PartA------------
数组名str:0099F7E0
数组名str取址:0099F7E0
数组名str取值:A
数组名str取值:ABCD
--------------PartB------------
数组名str[1]取址:0099F7E1
数组名str[1]取址:0099F7E1
数组名str[1]的值:B
数组名str[1]的值:B
分析:
partA部分:*(&str): 对str取址,其地址就是第一个元素的地址,然后再对它解引用,其值就是第一个元素的地址。
这点很混乱 ,我自己的理解就是,str如果看作是一个指针变量,它自身所在的内存地址,和他存的地址值是一样的。
partB部分:str[1]和*(str+1) 是一样的!涉及c语言的语法糖。
3.二维数组
运用上面的思维,相对很容就对二维数组进行分析。
设定二维数组:char array[4][5];
其储存结构如下:
编写代码,对地址进行分析
/*----------二维数组-----------*/
printf("--------------二维------------\n");
char array[4][5] = { "ABCD", "EFGH" , "IGKL","MNOP" };
//PartA
printf("--------------PartA------------\n");
printf("二维数组array的地址:%p\n", array);
printf("二维数组array的地址:%p\n", &array);
printf("二维数组array的地址:%p\n", *array);
//PartB
printf("--------------PartB------------\n");
printf("二维数组array[0]的地址:%p\n", array[0]);
printf("二维数组array[0]的地址:%p\n", &array[0]);
printf("--------------PartC------------\n");
//PartC
printf("二维数组array[1]的地址:%p\n", *(array+1));
printf("二维数组array[1]的值:%c\n", **(array + 1));
//PartD
printf("--------------PartD------------\n");
printf("二维数组array[0][1]的值:%c\n", *(array[0]+1));
printf("二维数组array[1][3]的值:%c\n", *(*(array + 1)+3));
结果:
--------------二维------------
--------------PartA------------
二维数组array的地址:0059FD50
二维数组array的地址:0059FD50
二维数组array的地址:0059FD50
--------------PartB------------
二维数组array[0]的地址:0059FD50
二维数组array[0]的地址:0059FD50
--------------PartC------------
二维数组array[1]的地址:0059FD55
二维数组array[1]的值:E
--------------PartD------------
二维数组array[0][1]的值:B
二维数组array[1][3]的值:H
分析:
1、由于数组增加到了二维,数组的名称名称也变成了2级 array 和 array[]。
2、array通过一次解引用得到的是array[0]的地址,array[0]再经过一次解引用,才能得到array[0][0]的值。
结论
对与二维数组和指针之间的关系目前的理解就是这样。结论如下
- 数组的变量名不同于指针变量,它的地址(&)就是数组第一个元素的地址,它的解引用(*)的值也是第一个元素的地址。相当于指针变量自身地址和存储的地址变量的值是一样的。(我存着我自己)
- 对于一位数组,函数名解引用完事第一个元素的地址。而对于二维数组,函数名解引用完是函数名[ ]的地址,函数名[ ]再解引用后才是第一个元素的地址。
- 属于初学阶段,希望能有更深的理解。