指针
1.指针是指针,数组是数组。指针与 数组没有关系。只是两者在用法上有点相似
2.数组传参要发生降维问题
3.数组是具有相同性质元素的集合
由于数组传参要发生降维问题,
1
2
3
4
5
6
7
8
9
10
11
12
13#include<stdio.h> void fun(int arr[]) //arr[],arr[10],*arr都可以,此时[]中的数字是被忽略的。 { printf("%dn",sizeof(arr)); } int main() { int arr[]={1,2,3,4,5,6,7,8,9,0}; printf("%dn",sizeof(arr)); fun(arr); return 0; }
运行结果
- 总结
只要是函数传参,传的是数组都要发生降维问题,降维为指针。
所有的数组(不管是几维的数组)都可以看成是一维数组
C程序认为的内存空间的布局规律
数组开辟空间时一次开辟数组长度的空间,然后按照a[0]—a[9],从小到大依次分配空间a[0]在低地置端。(在栈中储存)
- 每次调用函数就形成栈帧,函数返回释放栈帧.
1
2
3
4
5
6
7
8#include<stdio.h> int main() { char* pstr = "hellow bit."; printf("%sn",pstr); return 0; }
char* pstr放在栈区,"hellow bit."放在readonly区.char* pstr在main函数调用完后被释放,而"hellow bit."还在。而且"hellow bit."在 main函数结束后不会被释放,只会等待被覆盖。
降维问题的另一个表现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18#include<stdio.h> char *q=NULL; void fun(int arr[]) { char *s="hellow bit."; printf("%dn",sizeof(arr)); q=s; } int main() { int arr[10]={0,1,2,3,4,5,6,7,8,9}; printf("%dn",sizeof(arr)); fun(arr); printf("%sn",q); return 0; }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19#include<stdio.h> char *q=NULL; void fun(int arr[]) { char a[]="hellow bit."; printf("%dn",sizeof(arr)); q=a; } int main() { int arr[10]={0,1,2,3,4,5,6,7,8,9}; printf("%dn",sizeof(arr)); fun(arr); printf("%sn",q); return 0; }
- 由上述两个程序可以看出,在未进行传参的情况下(主函数中) sizeof(数组名)=40,而传参后变成了4.这就说明了参数传递的过程中存在着猫腻
函数调用完之后还能打印出函数内部字符串内容说明在readonly区储存的字符串内容在 main函数结束后不会被释放,只会等待被覆盖。.char* s在main函数调用完后被释放,而"hellow bit."还在。而用数组定义时调用完函数字符串就不在了。char a[ ]="hellow bit ."在[] 内没有标明字符串长度,但是系统会默认分配字符串长度个空间.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20#include<stdio.h> #include<string.h> int main() { char str1[]="hellow bit."; char str2[]="hellow bit."; char *str3="hellow bit."; char *str4="hellow bit."; if(str1 == str2) printf("str1 and str2 are same.n"); else printf("str1 and str2 are not same. n "); if(str3==str4) printf("sr3 and str4 are same.n"); else printf("str3 and str4 are not sanme.n"); return 0; }
运行结果
在同一个函数中定义两个内容相同的数组。但是他俩并不相等,因为在定义两个数组分别开辟了不同的空间。
指针数组
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16int* arr[10]; //整形指针的数组 char *arr[4]; //一级字符指针的数组 char **arr[5]; //二级字符指针的数组 int (*p)[10]; //数组指针 //p先和*结合,说明p是一个指针变量, //然后指针指向的是一个大小为10的整形数组。所以p是一个指针,指向一个数组,叫做数组指针。 //重点:[]优先级高于*的,所以必须先加上()来保证p先和*结合 int(*a[5])[10]; //数组指针的数组 int (*(*a)[5])[10]; //数组指针数组的指针 int (*(*a[5])[5])[10]; //数组指针数组指针的数组
操作符的优先级
数组名 and &数组名
int arr[10]={0,1,2,3,4,5,6,7,8,9}; // 其中的arr是数组名 ,数组名表示数组首元素的地址
两种特殊情况
1.在sizeof()出现数组名,则数组名表示的是整个数组。
-
(sizeof()中若出现数组名+/- n的形式则此时的数组名表示的是数组首元素的地址)
-
验证上述结论的真假
1
2
3
4
5
6
7
8
9#include<stdio.h> int main() { int arr[10]={0,1,2,3,4,5,6,7,8,9}; printf("sizeof(arr)=%dn",sizeof(arr)); printf("sizeof(arr+1)=%dn",sizeof(arr+1)); return 0; }
- 运行结果
- sizeof(arr) 值为40.大小为整个数组长度的大小.此处的arr指的是数组首元素的地址
- sizeof(arr+1)值为4,大小为一个int型指针的大小.此时的arr指的还是数组首元素的地址,其计算的是arr[1]的大小值
2.&数组名也表示整个数组。
- 除以上两种情况以外,数组名表示的是数组首元素的地址
1
2
3
4
5
6
7
8
9
10
11#include<stdio.h> int main() { int arr[10]={0}; printf(" arr= %pn",arr); printf(" &arr= %pn",&arr); printf(" arr+1= %pn",arr+1); printf(" &arr+1= %pn",&arr+1); return 0; }
- 运行结果
- 由以上程序和运行结果来看,&arr与arr虽然值是一样的,但是意义不同。
- 实际上:&arr表示的是数组的地址,而不是数组首元素的地址。
- 数组的地址+1跳过整个数组大小,所以&arr+1相对于&arr的差值是40.
- 对指针+1.其实是加上指针所指向类型的大小。
- 对指针+2,其实是加指针所指向类型的2倍。
数组传参降维问题
数组传参降维问题总结
-
1.只要是数组传参就会发生降维现象
-
2.只要发生降维现象就会降维成指针
-
3.降维成指向其内部元素的指针
-
4.所有数组都可以看成是一维数组,则所有数组都是线性的(计算机中的储存方式)
-
5.数组传参时,只有离数组名最近的维度可以省略[第一个维度].
-
代码一:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24#include<stdio.h>//只要发生降维现象就会降维成指针 void print_arr1(int (*arr)[5],int row, int col) { int i=0; int j=0; for(i=0;i<row;i++) { for(j=0;j<col;j++) { printf("%d ",arr[i][j]); } printf("n"); } printf("n"); } int main() { int arr[3][5]={1,2,3,4,5,6,7,8,9,0}; print_arr1(arr,3,5); return 0; }
代码二:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31#include<stdio.h> void print_arr1(int arr[3][5],int row, int col) //此处的3可写可不写 { int i=0; int j=0; for(i=0;i<row;i++) { for(j=0;j<col;j++) { printf("%d ",arr[i][j]); } printf("n"); } printf("n"); } int main() { int arr[3][5]={1,2,3,4,5,6,7,8,9,0}; print_arr1(arr,3,5); //数组名arr,表示首元素地址 //但是二维数组的首元素是二维数组的第一行 //所以这里传递的arr,其实相当于第一行的地址,是一维数组的地址。 //可以数组指针来接收 return 0; }
数组传参、指针传参
一维数组传参
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16//(此处的等价指能达到相同的效果) //两者等价 void test2 (int *arr[20])<==>void test2(int **arr) //三者等价 void test(int arr[])<==>void test(int arr[10])<==>void test(int *arr) //主函数: #include<stdio.h> int main( ) { int arr[10]={0}; int *arr2[20]={0}; test(arr); test2(arr2); return 0; }
二维数组传参
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16#include<stdio.h> //void test(int arr[3][5])//ok //void test(int arr[][])//no //void test(int arr[][5])//ok //void test(int *arr)//no //void test(int* arr[5])//no //void test(int(*arr)[5])//ok //void test(int **arr)//no int main() { int arr[3][5]={0}; return 0; } (此处将函数名注释掉是为了方便列举)
- 总结
二维数组传参时,函数形参只能省略第一个[]中的数字因为对一个二维数组,
可以不知道有多少行,但必须知道一行有多少元素
一级指针传参
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21#include<stdio.h> //一级指针传参 void print(int *p, int sz) { int i=0; for(i=0;i<sz;i++) { printf("%d ",*(p+i)); } printf("n"); } int main() { int arr[10]={1,2,3,4,5,6,7,8,9}; int *p=arr; int sz=sizeof(arr)/sizeof(arr[0]); print(p,sz); return 0; }
二级指针传参
验证代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16#include<stdio.h> void test(int **pr) { printf("num=%dn",**pr); } int main() { int n=10; int *p=&n; int **pr=&p; test(pr); test(&p); return 0; }
运行结果
由上述代码与运行结果来看,函数传参时上传的pr与&p所指向的目标是一样的。
变量与解引用
1
2
3
4
5
6int a=20; int *p=&a; //此处p指a的四字节空间 int *q=p; //此处的p指p四字节中的内容 一个指针指向一个变量,一旦经过解引用则*p代表的就是其指向的内容
最后
以上就是俊逸龙猫最近收集整理的关于关于数组传参那点事的全部内容,更多相关关于数组传参那点事内容请搜索靠谱客的其他文章。
发表评论 取消回复