1、数组类型
- C语言中的数组有自己特定的类型
- 数组的类型由元素类型和数组大小共同决定
- 例如:
int array[5] 的类型为 int[5]
- 例如:
1.1 定义数组类型
- C语言中通过typedef为数组类型重命名
typedef type(name)[size];
- 数组类型:
typedef int(AINT5)[5];
typedef float(AFLOAT10)[10];
- 数组定义:
AINT5 iArray;
AFLOAT10 fArray;
2、数组指针
- 数组指针用于指向一个数组
- 数组名是数组首元素的起始地址,但并不是数组的起始地址
- 通过将取地址符==&作用域数组名可以得到数组的起始地址==
- 可通过数组类型定义数组指针:
ArrayType* pointer;
- 也可以直接定义:
type(*pointer[n]);
- pointer为数组指针变量名
- type为指向的数组的类型
- n为指向的数组的大小
3、二维数组
- 二维数组在内存中以一维的方式排布
- 二维数组中的第一维是一维数组
- 二维数组中的第二维才是具体的值
- 二维数组的数组名可看做常量指针
3.1 数组名
- 一维数组名代表数组首元素的地址
int a[5] a的类型为int*
- 二维数组名同样代表数组首元素的地址
int m[2][5] m的类型为int(*)[5]
- 二维数组命可以看作一个数组指针
4. 数组方括号与指针的近似转换
int a[5];--> int*
a[5] --> int*(a+5);
int b[3][3];--> int(*)[3]
int *p[3] = b;
b[1][2] --> int*(*(p+1)+2)
方括号 [ ] 相当于将地址先偏移,再取值
5. 运用二级指针在内存中构造一个二维数组
- 二维数组常常被人们以矩阵的形式展示,并将二维数组的两个下标称为行和列
- 事实上,C语言中并不存在矩阵存储的方式,二维数组在内存中依然是以线性存储
- 知道了二维数组在内存的存储方式,我们就可以通过二级指针在堆空间中仿照其存储方式构建一个模拟的动态二维数组,它并不是真正的二维数组。
int** malloc2d(int row, int col) //用二维指针模拟二维数组
{
int** ret = NULL;
if( (row > 0) && (col > 0) )
{
int* p = NULL;
ret = (int**)malloc(row * sizeof(int*));//申请存放行指针的空间
p = (int*)malloc(row * col);//申请存放数组总空间
if( (ret != NULL) && (p != NULL) )
{
int i = 0;
for(i = 0; i < row; i++)
{
ret[i] = p + i * col;//ret[i] <=> *(ret + i)
} //将p空间均分成row份
//将每一份的首地址保存到ret空间中
}
//9~18行参考上图
else
{
free(ret);
free(p);
ret = NULL;
}
}
return ret;
}
void free2d(int** p)
{
if( *p != NULL )
{
free(*p) //先释放p空间
}
free(p); //再释放ret空间,调转顺序会丢失存储在ret里的p的地址,导致无法正常释放p空间
}
下面是主函数的调用和二维数组的输入输出
int main(int argc, const char *argv[])
{
int** a = malloc2d(3, 3);
int i = 0;
int j = 0;
for(i = 0; i < 3; i++)
{
for(j = 0; j < 3; j++)
{
scanf("%d", *(a+i)+j);
}
}
for(i = 0; i < 3; i++)
{
for(j = 0; j < 3; j++)
{
printf("%d ", *(*(a+i)+j));
}
puts("");
}
return 0;
}