C语言数组分析
数组和指针之间本来没有什么关系,数组就是数组,指针就是指针,之间并没有关系,只是因为某些相似特性使得我们在分析的过程中存在较大的迷惑。
数组就是一个连续存储空间的存储的数值。指针就是指针,指针变量所在内存中存储的值都是地址。
C 语言中数组的大小必须是一个常数,但是不能认为采用const限定的变量就能作为数组大小的值,在C语言中const并不是定义一个常数,只是定义了一个只读类型的数据,并不是常数。在C语言中通常采用:
#define N 5
int Array[N];
const int M = 5;
int Array[M];//这是一种错误的定义方式,注意const并不是定义常量,但是C++中可以这样定义。
在一维数组中使用下标来访问数组,Array是整个分配存储空间的名字,单个的存储空间并没有名字。这个存储空间存储的值为数组的元素,主要是 Array[0],Array[1],...,Array[N-1],数组元素并没有名字。我们对数组的访问主要是采用下标的方式进行访问。Array与这块存储空间已经密切的关联起来,不能改变。但是需要主要的是Array作为右值时,表示的是该数组首个元素(Array[0])的地址,而不是代表整个数组的地址起始地址,虽然两个起始地址是相同的,但是需要理清其中的概念。整个数组的起始地址可以通过对这块存储区域取地址,也就是采用&a,这时得到的值才是整个数组的起始地址,虽然两个值是相同的,但是需要搞清楚其中的道理。
在数组中位置的变化也是非常重要的。
int *p = NULL;
p = Array + 1;
是指在数组Array的首元素的首地址上增加一个元素的宽度,使得p指向Array[1]。因为Array表示的是数组首个元素的首地址,那么操作的最小单位就是元素,Array + 1就是访问下一个元素。
p = &Array + 1;
由于&Array是表示数组的起始地址,操作的最小单位是一个数组,而不是元素,因此Array+1就是下一个数组的起始地址,也就是将p指向了Array的下一个数组,而不是元素。
因此需要注意一维数组名在作为右值时是表示数组首个元素的首地址,并不表示整个数组的首地址。
对于二维数组(多维数组)也存在类似的问题。
int *p = NULL;
#define N 5
#define M 5
int A[N][M];
数组A存在5个元素,每一个元素是一个数组,每个数组中存在5个元素。数组名A表示首个元素的首地址,因此A表示A[0]的首地址,A的元素为数组,A + 1表示下一个元素(小数组)也就是A[1]的首地址;&A表示整个数组的首地址。&A+1表示下一个数组的起始地址。
A作为右值时,表示数组首元素的首地址,也就是A[0]的首地址,A[i]作为右值时是表示第i个元素(也是数组)的首元素(A[i][0])的首地址。由于A表示地址,这与指针存在很多的相似性,因此可采用指针的方式进行访问。具体的实现过程如下:
A %%第0行的元素的首地址,不是第0行第0个元素的地址
A[i] <---> *(A+i); %%第i行第0个元素的地址
A[i][j] <---> *(*(A+i)+j); %%第i行第j个元素
&A[i][j] <---> (*(A+i)+j); %%第i行第j个元素的地址
A[i]+j <---> (*(A+i)+j); %%第i行第j个元素的地址
&A+1 %%下一组数组的起始地址
A+i %%第i行数组的起始地址
在多维数组中存储方式是线性的存储方式,可以通过指针快速的访问。首先A表示首元素的首地址,将指针指向这个首地址就能快速的实现访问。
为了说明这些相互关系的,采用GDB对数组进行调试:
int main()
{
int i = 0,j = 0;
int a[5][5];
int b[5]={4,5,7,8,9};
for(;i < 5; ++i)
for(;j<5;++j)
a[i][j] = (i-j)+15;
}
编译调试:
(gdb) p a
$1 = {{15, 14, 13, 12, 11}, {32768, 8736756, 8729060, -1073744844,
-1073745080}, {0, -1073744928, 134518436, -1073745064, 134513340}, {
7298965, 134518436, -1073745016, 134513785, 134513194}, {8740000, 8740000,
8736756, 134513760, 134513408}}
(gdb) p &a
$2 = (int (*)[5][5]) 0xbffff314
(gdb) p &a+1
$3 = (int (*)[5][5]) 0xbffff378
(gdb) p a+1
$4 = (int (*)[5]) 0xbffff328
(gdb) p *(a+1)
$5 = {32768, 8736756, 8729060, -1073744844, -107
C语言数组分 相关文章:
- Windows CE 进程、线程和内存管理(11-09)
- RedHatLinux新手入门教程(5)(11-12)
- uClinux介绍(11-09)
- openwebmailV1.60安装教学(11-12)
- Linux嵌入式系统开发平台选型探讨(11-09)
- Windows CE 进程、线程和内存管理(二)(11-09)