c语言中数组的地址,有着一些非常奇妙的性质。经过个人实验,我暂时总结了如下两点:
- c语言中任何数组地址类型均为 void*。
#include<stdio.h>
int main()
{
double a1[3][3];
int a2[3][3];
char a3[3][3];
int a4[3];
int a5[3][3][3];
void *p1 = a1;
void *p2 = a2;
void *p3 = a3;
void *p4 = a4;
}
上述代码均可在编译器中无warning通过。无论数组是几维,也无论数组中元素是何类型,数组的地址类型均为void*。相反,如果将其指针类型改为对应元素的类型,如下所示:
#include<stdio.h>
int main()
{
double a1[3][3];
double *p1 = a1;
}
则会出现这样的警告:
[Warning] initialization from incompatible pointer type [enabled by default].
说明变量声明的类型与其实际类型不符。
但是,在实际操作中,我们为了方便阅读,防止指针使用错误,还是要用如上方法定义指针。那么,这里就需要用到强制类型转换,这样我们就可以消除warning了。例子如下:
#include<stdio.h>
int main()
{
double a1[3][3];
double *p1 =(double*) a1;
}
2.对于多维数组,其首地址既是第一个元素的地址,同时,其数值也是其本身的地址。这样的说法有点奇怪,我们来看一个例子:
#include<stdio.h>
int main()
{
int a[3][3][3]={0};
printf("%d\n", a);
printf("%d\n", &a);
printf("%d\n", a[0]);
printf("%d\n", a[0][0]);
printf("%d\n", &a[0][0][0]);
}
在我的电脑上运行它,得到的结果为:
可以看到其数值完全一致。
但是,虽然他们数值一致,在调用时却任然有差别:
#include<stdio.h>
int main()
{
int a[3][3][3]={0};
printf("%d\n", a);
printf("%d\n", *a);
printf("%d\n", **a);
printf("%d\n", ***a);
printf("%d\n", **a[0]);
printf("%d\n", *a[0][0]);
}
运行上述代码,得到结果为:
可以看到,在调用时,就不能之将其类型统统看作void*,而要区分其具体的类型,否则可能输出的是地址,而不是其指向的元素。