前言
此博客参考借鉴了《C Traps and Pitfalls》
正文
1.对于任何一个数组我们可以确定数组的大小,获取指向该数组下标为0的元素的指针。这实际上都是通过指针进行的。换句话说我们可以通过指针的行为定义数组下标的行为。
1.数组的声明
stcuct
{
int p[4];
double x;
}b[17];
这里声明了b是一个拥有17个元素的数组,其中每一个元素是一个结构体,每个结构体包括了一个拥有4个整形元素的数组,和一个double类型变量。
int calendar[12][31];
这个语句声明calendar是一个数组,这个数组有12个数组类型的元素,每一个元素都是一个拥有31个整形元素的数组。
所以如果calendar不是sizeof的操作数,而是用于其他场合,那么calendar会被转化成一个指向calendar数组起始元素的指针
2.指针
如果一个指针指向的是数组中的元素,那么我们给指针+1就可以指向数组下一个元素,同理-1类似。
由此可知给指针+/-一个整数,表示为指向计算机内存的下一个整数
所以我们可以得出:
如果指针指向的是同一个数组的元素,两个指针相减可以得出中间的元素个数。
注意:如果两个指针指向的不是同一块空间,则两个指针相减没有任何
意义,是一个随机值。
3.数组名与&数组名
声明int a[10]={0}; int* p;
p=a;数组名会被当成指向该数组下标为0的元素的指针。
p2=&a这表明取出的是数组整个的地址,p+1会跳过整个数组,但p2与p的值相同,都是数组首元素的地址。
注意:p2=&a在严格意义上是非法的,因为&a是一个指向数组的指针,而p2是一个指向整形变量的指针,他们的类型不匹配。
4.a[i]=*(a+i)
定义a是整型数组。
*a=80表示将数组的首个整形元素大小改为80。由此可以类比
*(a+i)表示数组下标为i的元素简记为a[i]
再考虑二维数组
声明
int calendar[12][31];
int* p;
int i;
calendar数组有12个元素。每个元素是一个有31个整形元素的数组,所以
calendar[4]表示calendar第5个元素,是一个数组。因此calendar与一个有31个整形元素的数组的性质相类似。
eg:sizeof(calendar[4])=31*sizeof(int);
由上可知:
再看:p=calendar;
这句话是非法的因为calendar名称会转化成一个指向数组的指针,但是p是一个指向整形元素的指针,类型不匹配。
所以要想上式成立p的定义要改为
int(*p)[31]这表明了p是指针,指向了一个含有31个整形元素的数组。
结尾
所以下面代码
int month;
for(mouth=0;mouth<12;mouth++)
{
int day=0;
for(day=0;day<31;day++)
{
calendar[month][day]=0;
}
}
可以用指针写成
int(*month)[31];
for(month=calendar;month<&calendar[12];month++)
{
int* day;
for(day=*month;day<&(*month)[31];day++)
{
*day=0;
}
}
由上面可以看出,用a[i]来表示*(a+i)更方便。但上面的式子对于我们更好的理解数组与指针有帮助。
此博客参考了《C Traps and Pitfalls》,有什么问题欢迎指正