一.数组名就是指针?
相信听过这样的话:数组名就是指针。这不管是我们的授课老师,还是有些程序设计的书籍中都有这样说过。
但是,这样并不严谨。他是指针,他又不完全是。
现在来看一看数组表达式:ary[1]。显而易见,这是指数组中的第二个元素。
但是在编译器看来,这个表达式看作是*(ary+1)。这意味着实现的方法是先找到地址,再取其中的值。这里和指针异曲同工。
看代码:
程序清单 1.1
char str[]="123456";
char *c=str;
cout<<"*str:"<<*str<<endl;
cout<<"*c:"<<*c<<endl;
运行结果:
从程序的输出可知:
*数组名 ,*指针, 数组名[ ]取值时是等价的。
在这种情况下,可以用相同的方式使用数组名和指针。但是有一个显著区别就是,指针是变量,可以修改值。数组名是常量。意思就是取值时,你可以 *(指针++) ,但是不可以 *(数组名++)
但是为什们说数组名不能直接说是指针呢?
1.第一点
我们对数组名使用sizeof运算符时得到的是数组的长度(占内存的大小),而对指向数组的指针使用该运算符时得到的却是指针的大小(往往是4字节)。
代码:
程序清单1.2
char str[]="123456";
char *c=str;
cout<<"sizeof(str):"<<sizeof(str)<<endl;
cout<<"sizeof(c):"<<sizeof(c)<<endl;
system("pause");
运行结果:
这我们数组名和指针都是指向的同一个数组,但是得到的值确违背人意,因为按照我们上面的实现方法得不到我们想要的值。(注:
这里为啥会是这样的结果,我们等会下面会解释)
2.第二点
下面这段代码就很意思,让作者也感到意想不到
程序清单1.3:
void text(char str[]){
cout<<"sizeof(str):"<<sizeof(str)<<endl;
}
int main(){
char cs[10]="messi";
cout<<"sizeof(cs):"<<sizeof(cs)<<endl;
text(cs);
system("pause");
return 0;
}
读者可以先想5s,猜猜输出结果是啥?
5
4
3
2
1
运行结果:
函数中的输出结果 居然是4,有读者可能已经猜到,现在此时,数组名就是指针了。
为什们呢?
因为数组名在在作为形参传递的时候,遭到了降维打击,可以说是被强制转换为了一个指向该数组的普通指针。不能在作为原始数组。
这意味着,在此函数内,该数组名可以进行修改值的操作。
。
。
二.数组名一定会被解释第一个元素地址吗?
有基础的读者知道,数组名单独拿出时往往是数组的第一个元素的地址(就是指针),
但是不完全如此,我们在程序清单1.2中,sizeof运算符中,数组名是第一个元素的地址,指针也是第一个元素的地址,但是运行结果却是截然相反呢?
因为:对数组名应用地址运算符时,得到的是整个数组的地址
话不多说,上代码:
程序清单2.1:
int ary[5]={1,2,3};
cout<<"ary:"<<ary<<endl;
cout<<"ary+1:"<<ary+1<<endl;
cout<<"&ary:"<<&ary<<endl;
cout<<"&ary+1:"<<&ary+1<<endl;
system("pause");
注:不知道有读者会不会像作者曾经一样,将 &ary 看作是取数组首地址的地址,这是错误的错误的!! 而是得到整个数组的地址。
5
4
3
2
1
运行结果:
从,数字上来看,ary和&ary得到的地址相同,但是两个的概念截然不同。
ary 是一个4字节大小内存块的地址;
&ary 是一个20字节大小内存块的地址;
ary+1 是地址值+4(一个int);
&ary+1 是地址值+20(数组的长度);
那么 &ary如何描述呢?
int (*p) [5]=&ary ;
括号是不能省略的,如果省略括号的话,p先和 [5] 结合,导致p是一个指针数组。
这里顺便讲一句,如何确定指针的自身类型?
将变量名丢掉,剩下的就是指针的自身类型。
如何确定指针指向的类型?
将变量名和最近的 *删除,剩下的就是指向的类型。
所以:我们在平常时称数组名为第一个元素的地址更恰当,因为只说时数组的起始地址的话,不知道数组名+1的跨度为多少。
。
·