理解数组的概念和对数组的灵活使用,对学好指针十分重要。
目录
一维数组
char array[2]; 一个char类型的一维数组,在内存中占有两个地址连续的存储空间,它所存储的元素都是相同类型的。注意:数组的下标是从0开始。元素即array[0],array[1]。
现在给array赋值来测试一下。在linux环境下,char array[2]="hi",printf("array is =%s\n",array); 发现确实打印了hi,但是hi后面是乱码的,因为"hi"这个字符串最后面还有"/0",所以字符串"hi"占3个字节。但是数组array只分配了2个字节的存储空间,内存不够导致数组越界。(如果用vs等IDE,会直接报错)。
只需要把array[2]改成array[3]就可以正常打印。通常写为char array[2+1]。
数组array的地址其实就是array[0]的地址,因为数组名的地址就是数组首元素的地址,而数组是地址连续的存储空间,所以通过获得数组首元素的地址,就可以遍历得到后面所有数组元素的地址。
示例代码
#include<stdio.h>
int main()
{
char buf[2]="hi";
printf("buf is %s\n",buf);//打印hi,但是会出现乱码,数组越界
char array[3]="ok";
printf("array is %s\n",array+1);//打印k
char *p=array;
printf("p is %s\n",p);//所以这里打印ok
printf("p+1 is %s\n",p+1);//打印k,k+1和array+1打印的结果一样
return 0;
}
指针的概念
在上面的代码,定义了一个指向char类型的指针变量p
至于打印p+1为什么输出k,首先p+1是一个指针操作,指针p指向了array[0]的地址,而数组的元素的地址是连续的,
所以p+1,就是array[0]的地址+1,&(array[0]+1)=&array[1],所以array[1]存放的元素是k。即p+1打印k。
注意:* 表示p是一个指针变量。这里的*其实是重载符号,因为*也是乘的意思。
对于一维数组,还有以下几个概念
char a[]={1,2,3,4}; 如果在花括号中给定了数组各个元素的值,就不需要在[ ]中写上4,因为系统知道,我们分配了4个元素,所以1,2,3,4会依次存放在数组中。如果只写成char a[];没有定义值,那么就是错误的。因为计算机不知道要给这个数组分配多大的内存空间。
数组还可以这样写,char a[3]={1,2}; 给数组a赋值了1和2,但是地址是3个,经过打印发现,编译器会默认把a[2]的值打印0。很多概念当不清楚的时候,写一段代码检验一下,就可以知道事情的真相了。发现我们程序员很适合这句话,实践是检验真理的唯一标准。
----------------------------------------------分割线------------------------------------------------------------------
二维数组
二维数组是特殊的一维数组。对于二维数组,我们举例说明。
int a[2][3]={1,2,3,4,5,6}; 这里定义了一个数组名为a的二维数组,平面化的理解就是,这是一个2行3列的数组
1 | 2 | 3 |
4 | 5 | 6 |
a[0][0]=1 a[0][1]=2 a[0][2]=3
a[1][0]=4 a[1][1]=5 a[1][2]=3
平面化的概念便于我们观察二维数组各个元素的值。但是,在计算机中,任何数值都是存放在内存中的,2行3列的平面概念不利于加深对内存的理解。
如果把数组比喻成各种各样的房子,就有立体感了,就能更好的理解计算机内部的存储原理。
对于一维数组int a[3]={1,2,3}; 可以把它看做是3个连续的房子A,B,C即(a[0],a[1],a[2]),房子里面分别存放了 1,2,3这三个货物,因为房子是连续的,所以我们通过房子A,就可以找到房子B,然后找到房子C。当然如果我们知道C的地址,也可以通过C来找到A和B的地址。无论有多少房子,只要我们找到了第一个,或者其中一个,可以知道其他房子的位置(即地址)。
二维数组也是一样,它是特殊的一维数组,int a[2][3]={1,2,3,4,5,6} ;
其实是a这个房子里,存放了两个箱子(a[0],a[1]),而这两个箱子里面呢,又分别存放了3个小箱子(a[0][0],a[0][1],a[0][2]) 与 (a[1][0],a[1][1],a[1][2]),这就是二维数组。我们发现它们其实都是一维数组组成的,所以称之为特殊的一维数组。
下一篇 C语言指针