指针与数组的根本区别在于,指针存放的内容是“数据的地址”, 而数组存放的内容,就是数据本身。
访问指针指向的数组时,编译器首先取得指针存放的地址,如果指针有一个下标[I],就把指针的内容加上作为地址,从该地址中取数据。
而访问数组a时,a就是存放数据的地址,编译器直接从该地址中取数据,如果数组有一个下标[I],就把该地址加上I作为地址,从该地址中取数据。
也就是说,访问指针比访问数组多了一个获取地址的过程。
另外,数组和指针都可以在它们的定义中用字符串进行初始化,尽管看上去一样,底层的机制却不同。
定义指针时,编译器并不为指针所指向的对象分配空间,它只是分配指针本身的空间,除非在定义时同时赋给指针一个字符串常量:
char *p = "this is read only string"; //该字符串常量存放于可执行文件的只读数据区
char a[] = "this string can be modified"; //编译器将在堆栈中为a分配存储空间。
什么时候数组和指针是相同的?
C语言标准:
1. 表达式中的数组名(与声明不同)被编译器当作一个指向该数组每一个元素的指针
2. 下标总是与指针的偏移量相同
3. 在函数参数的声明中,数组名被编译器当作指向该数组第一个元素的指针
(1) “表达式上的数组名“就是指针
假设有如下声明:
int a[10], *p, i=2;
我们可以通过下面任何一种方法来访问a[i]:
p = a;
p[i];
p=a;
*(p+i);
p=a+i;
*p;
(2) 在函数参数的声明中,数组名被编译器当作指向该数组第一个元素的指针(因为如果拷贝整个数组的话无论是内存还是时间都是一个很大的开销)
int array[100], array2[100];
main(){
array[1] = 3;
*arr = 3;
array = array2; //不合法,因为array是一个数组名,而数组名是不可修改的左值。
}
//但是
fun( int arr[] ){
arr[1] = 3;
*arr = 3;
arr = array2; //合法,因为arr实际上是一个指针
}