1. 数组名特性
1.1 作为常量指针特性(运算、寻址特性)
1) 特性:数组名作为一个指向数组首地址的常量指针
2) 条件:(满足其一即可)
- 算术运算时
- 间接寻址运算
3) 注意:
3.1) 数组名作为常量指针,既然是常量就不可以赋值,即数组名的地址不可以改变
例1: 直接对数组名赋值
int arr[] = {0};
int arr2 [] = {1};
arr1 = arr2; //错误,数组名作为常量指针不可以在赋值
例2: 间接对数组名赋值
int arr[] = {0,1};
arr++;//错误,arr++ 等价于 arr=arr+1
3.2) 间接改变数组名的指向
例1: 通过赋值给指针类型
int arr[] = {0,1};
int *p = arr;
p++;//改变的不是arr,而p
例2: 通过传递参数
void test(int *p){
p++;
}
int main(){
int arr[] = {0,1};
test(arr);//传递数组名的过程,本质是copy指针给到新栈
}
1.2 取地址特性
1)特性 对数组名取地址获取的指向数组的指针
注意指向数组的指针和指向数组地址首元素的指针,其意义在算术运算上完全不同
2)条件:
对数组名取指针 &arr(注意,数组名不能是函数参数,因为函数参数本质是copy指针,已经不算数组名的范围)
3) 注意:
3.1) 无法直接改变数组名的指向
常量可以通过指针修改,而常量指针可以通过二级指针修改,既然数组名作为"常量指针"(特性),那么理论上可以通过二级指针去修改。
然后实际上不可以修改数组名指向,其核心原因在在于无法获取二级指针
例如int arr[] = {0,1,2};
,当我们 &arr
时,由于并没有计算,所以无法作为常量指针,&arr
获取的是作为数组的指针,而当我&((int *)(&arr))
就得到不能获取地址的错误。
3.2) arr和&arr的区别
其本质区别在于:
arr是指向数组地址首元素的指针,而&arr是指向数组的指针。
两者在指向的地址完全一样,但是类型不同,从而决定着算术运算不同。
即 arr+1 和 &arr +1 ,一个是获取第二个元素指针,一个是获取第二个数组的指针,此时arr+1 指向 arr[1]
而 &arr+1 指向 arr[arr_len]
。
1.3 获取大小特性
1)特性:对数组名sizeof时获取的整个数组的字节数
2) 条件
对数组名sizeof (注意,这里数组名不包含形参)
3) 注意
3.1) 对比 sizeof数组名和sizeof指针
sizeof是由编译器算出,而编译器只会根据变量的类型去算出长度
int arr[3];
int *p = arr;
printf("%ld\n", sizeof(arr));//12
printf("%ld\n", sizeof(p));//8
1.4 作为实际参数 特性
1)特性 数组名在传递给函数时,并不是copy一份数组,而是copy一个指向数组首元素的指针
2) 条件
将数组名传递给函数
3) 注意
3.1) 无论形式参数采用 [ ]
申明还是采用 *
声明。编译器都看成指针类型
例1:比较数组名和数组名指针
下面编译时会报:
sizeof on array function parameter will return size of 'int *' instead of 'int []'
,这进一步说明编译器将[ ]
和*
看成一致,全部指针类型。
注意上述是针对形参而言,而非声明,声明[ ]
和*
则完全不同
void test(int arr[] , int *arr1){
printf("%d\n", sizeof(arr) == sizeof(arr1));//1
}
int main(int argc, char const *argv[]){
int arr[10];
int *arr1 = arr;
printf("%d\n", sizeof(arr) == sizeof(arr1));//0
test(arr,arr1);
return 0;
}
2. [] 和 * 的不同
来源:oschina
链接:https://my.oschina.net/lianghao0/blog/4276291