概述
指针
1.指针是指针,数组是数组。指针与 数组没有关系。只是两者在用法上有点相似
2.数组传参要发生降维问题
3.数组是具有相同性质元素的集合
由于数组传参要发生降维问题,
#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]在低地置端。(在栈中储存)
- 每次调用函数就形成栈帧,函数返回释放栈帧.
#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函数结束后不会被释放,只会等待被覆盖。
降维问题的另一个表现
#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;
}
#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 ."在[] 内没有标明字符串长度,但是系统会默认分配字符串长度个空间.
#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;
}
运行结果
在同一个函数中定义两个内容相同的数组。但是他俩并不相等,因为在定义两个数组分别开辟了不同的空间。
指针数组
int* 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的形式则此时的数组名表示的是数组首元素的地址)
-
验证上述结论的真假
#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.&数组名也表示整个数组。
- 除以上两种情况以外,数组名表示的是数组首元素的地址
#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.数组传参时,只有离数组名最近的维度可以省略[第一个维度].
-
代码一:
#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;
}
代码二:
#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;
}
数组传参、指针传参
一维数组传参
//(此处的等价指能达到相同的效果)
//两者等价
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;
}
二维数组传参
#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;
}
(此处将函数名注释掉是为了方便列举)
- 总结
二维数组传参时,函数形参只能省略第一个[]中的数字因为对一个二维数组,
可以不知道有多少行,但必须知道一行有多少元素
一级指针传参
#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;
}
二级指针传参
验证代码
#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所指向的目标是一样的。
变量与解引用
int a=20;
int *p=&a; //此处p指a的四字节空间
int *q=p; //此处的p指p四字节中的内容
一个指针指向一个变量,一旦经过解引用则*p代表的就是其指向的内容
最后
以上就是俊逸龙猫为你收集整理的关于数组传参那点事的全部内容,希望文章能够帮你解决关于数组传参那点事所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复