2维数组与动态创建2维数组。
一维数组的逻辑概念是一组数据,由下标指向。在内存分配上是连续的
二位数组的逻辑概念是一个表,由行,列来指向。数据的存储方式通常是按行存储的。
在内存的分配上要看这个二维数组元素到底是什么结构.
例如: a 是一个2维静态数组,,则int a[i][j], 逻辑上指第i行的第j个数据。那么其数据地址是如下计算的
举例: int a[2][3], 固定的2行3列静态数组
则:&a[i]=a+i*3*sizeof(int) // 地址只是一个计算方法,并不实际用内存存放该地址
则: &a[i][j] = a+i * 3*sizeof(int) +j *sizeof(int) , 数据在内存上是连续的.
例如 a 是一个2维指针,int **a, 则a[i]是一个一维指针,
则: &a[i]=a+i*sizeof(int *) // 注意,存放的是指针!
则: &a[i][j] = (*&a[i]) + j * sizeof(int *) .
就是说先取出a[i]地址处的内容为基地址,再加上j个元素的偏移地址
由以上分析知道,&a[i][j]内存地址计算方法,根据a的类型不同,是静态数组?还是指针?将有不同的计算方法.
------------------------------------------------------------
静态2维数组示例:
------------------------------------------------------------
#include "stdafx.h"
#include <conio.h>
int a[2][3]=
{
11,12,13,
21,22,23
};
int main(int argc, char *argv[])
{
for(int i=0;i<2;i++)
{
for(int j=0;j<3;j++)
{
printf("a[%d][%d] is %d\n",i,j,a[i][j]);
}
printf("\n");
}
_getch();
return 0;
}
------------------------------------------------------------
动态创建2维数组 -- 两种方法:
------------------------------------------------------------
方法1.先申请全部行首指针,再按行逐行申请,常规方法,用法简单,我通常还是用此法。
------------------------------------------------------------
#include "stdafx.h"
#include <conio.h>
int main(int argc, char *argv[])
{
int **a = new int *[2];
for(int i=0; i<2; i++)
{
a[i]=new int *[3];
}
// 先申请完内存,然后再赋值
_getch();
return 0;
}
注意, 这样分配的内存,有多块内存, a[i][j] 是指向多个内存块的。
注意2, int 和 int * 大小是不一定相等的,例如在64bits机器上,前者为4,后者为8.
曾经有一个程序按int 保存指针大小,在32bits 上没发现问题,在64bits上总是崩溃,就是这个原因造成.修改后解决问题.
------------------------------------------------------------
方法2.转化为一维数组申请,
实际上也是方法1,只是巧妙安排了行首指针,使指针与数据连接在一起。
并且让指针所指的位置,正好与静态数组的计算方法相同.
这样,a[i][j] 数据可以集中到一个内存块中,就是所说的连续的内存空间了。 释放内存也方便了,只释放一次便可。
------------------------------------------------------------
用法:(像静态数组一样使用动态数组,只申请一次内存,创建过程稍微复杂一点)
struct xxx **data = (struct xxx **) arr_new(2, 3, sizeof(struct xxx));
这里就可以用 data[1][2] ... data[0][1] ... 来操作了:)
arr_free(data);
完整示例:
#include "stdafx.h"
#include <conio.h>
#include <stdlib.h>
#include <string.h>
void **darray_new(int row, int col, int size);
int main(int argc, char *argv[])
{
int **a = (int **)darray_new(2,3,4);
for(int i=0; i<2; i++)
{
for(int j=0; j<3; j++)
{
a[i][j]=i*j;
}
}
_getch();
return 0;
}
void **darray_new(int row, int col, int size)
{
void **arr;
arr = (void **) malloc(sizeof(void *) * row + size * row * col);
if (arr != NULL)
{
char *head;
head = (char *) arr + sizeof(void *) * row;
memset(arr, 0, sizeof(void *) * row + size * row * col);
while (row--) // row 为1时,向0行填充,为0时退出,刚好满足要求
arr[row] = head + size * row * col;
}
return arr;
}
void darray_free(void **arr)
{
if (arr != NULL)
free(arr);
}