数组
来源:互联网 发布:tensorflow python 编辑:程序博客网 时间:2024/06/06 04:46
最近看了一些关于C/C++语言中数组的资料,发现以前的理解确有不妥。所谓数组并不是简单的元素阵列,而是一种数据类型或数据结构。数组名也并不是简单的常量指针,是一个数组类型的变量,其值为数组中第一个元素的地址。
int a[2][2][3]={{{10,6,3},{5,4,15}},{{3,5,33},{23,12,7}}};
typeof(a) b = {0}; // 说明a是一种不同于普通指针的数据类型,见sizeof输出
printf("sizeof(a): %d/n", sizeof(a)); // 48 = 12 * sizeof(int)
printf("sizeof(b): %d/n", sizeof(b)); // 48 = 12 * sizeof(int)
数组和指针的对应关系:
int *p1 = a; // error
int **p2 = a; // error
int ***p3 = a; // error
int (*p4)[2][3] = a; // OK
printf("sizeof(p4): %d/n", sizeof(p4)); // 4, 指针大小
printf("0x%p/n", a); // 0x0022FF30, 数组首地址
printf("0x%p/n", &a); // 0x0022FF30, 数组首地址, 和指针变量有区别
printf("0x%p/n", p4); // 0x0022FF30, 数组首地址
printf("0x%p/n", &p4); // 0x0022FEFC, p4自身的地址
printf("0x%p/n", *p4); // 0x0022FF30, 数组首地址
printf("0x%p/n", **p4); // 0x0022FF30, 数组首地址
printf("0x%p/n", ***p4); // 0x0000000A, a[0][0][0]的值
数组类型和指针类型的对应关系可总结为:
ElemType a[M][N][O]…[X][Y][Z] ↔ ElemType (*pa)[N][O]…[X][Y][Z]
多维数组的使用必须遵循这个等价关系才能做到类型安全。
多维数组的动态分配:
int *p5 = new int[10]; // OK
int *p6 = new int[8][10]; // error
int **p7 = new int[8][10]; // error
int (*p8) [10] = new int[8][10]; // OK, 如果语言支持“int[10] (*p8)”则更好理解
数组的不同访问方法(这里不讨论常用的用“[]”访问元素的方法):
int i,j,k;
for (i=0;i<2;i++)
for (j=0; j<2; j++)
for (k=0; k<3; k++)
printf("%d ", *(*(*(a+i)+j)+k));
printf("/n");
for (i=0;i<2;i++)
for (j=0; j<2; j++)
for (k=0; k<3; k++)
printf("%d ", *(**a + i*2*3 + j*3 + k));
printf("/n");
for (i=0; i<2; i++)
for (j=0; j<6; j++)
printf("%d ", *(**(a+i)+j));
printf("/n");
for (i=0; i<2; i++)
for (j=0; j<6; j++)
printf("%d ", *(**a + i*2*3 + j));
printf("/n");
for (i=0; i<12; i++)
printf("%d ", *(**a+i));
printf("/n");
对于一个二维数组int array[m][n]而言以下4中表达方法是等价的。
array[i][j]
*(array[i]+j)
(*(array+i))[j]
*(*(array+i)+j)
数组名作为函数的参数:
// array退化为int *array,array是一个指针
// C/C++把数组传递改写为指针传递的主要原因有:
// 1) 数组在内存中是连续字节存放的,编译器可以通过地址计算来引用数组中的元素
// 2) 出于性能考虑,如果把整个数组的元素全部传递进去,不仅需要大量时间来拷贝数组,拷贝操作还会占用
// 大量的栈空间
// 从后面的输出可以看出array和array+1相差4,即sizeof(int)
void func1(int array[], int size)
{
printf("sizeof(array): %d, 0x%p, 0x%p/n", sizeof(array), array, array+1);
}
void func2(int *array, int size)
{
printf("sizeof(array): %d, 0x%p, 0x%p/n", sizeof(array), array, array+1);
}
// array退化为int (*array)[10] ,array是一个指针
// 向函数传递多维数组时不需要说明第一维的大小而必须说明其他所有维的大小,主要原因有:
// 1) 数组在内存中按照“行优先”规则存储,所以需要列数来确定一行有多少个元素
// 2) 编译器在计算元素的地址时不需要数组第一维的长度,但是需要其他维的长度信息
// 3) C/C++不对数组进行越界访问检查,因此对编译器来说不需要知道第一维的长度
// 从后面的输出可以看出array和array+1相差40
// 这说明array并不是一个普通的指针,它指向的数据类型大小为40,即10*sizeof(int)
void func3(int array[][10], int line)
{
printf("sizeof(array): %d, 0x%p, 0x%p/n", sizeof(array), array, array+1);
}
void func4(int (*array)[10], int line)
{
printf("sizeof(array): %d, 0x%p, 0x%p/n", sizeof(array), array, array+1);
}
int array1[10];
int array2[8][10];
func1(array1, 10); // sizeof(array): 4, 0x0022FEB0, 0x0022FEB4
func2(array1, 10); // sizeof(array): 4, 0x0022FEB0, 0x0022FEB4
func3(array2, 8); // sizeof(array): 4, 0x0022FD70, 0x0022FD98
func4(array2, 8); // sizeof(array): 4, 0x0022FD70, 0x0022FD98