C语言-数组和指针【未完待续】

谁说胖子不能爱 提交于 2020-08-06 02:02:03

1. 数组名特性

1.1 作为常量指针特性(运算、寻址特性)

1) 特性:数组名作为一个指向数组首地址的常量指针

2) 条件:(满足其一即可)

  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. [] 和 * 的不同

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!