关于数组传参那点事

指针

1.指针是指针,数组是数组。指针与 数组没有关系。只是两者在用法上有点相似

2.数组传参要发生降维问题

3.数组是具有相同性质元素的集合

由于数组传参要发生降维问题,

#include<stdio.h>
  void fun(int arr[])            //arr[],arr[10],*arr都可以,此时[]中的数字是被忽略的。
   {
       printf("%d\n",sizeof(arr));
   }
  int main()
  {
      int arr[]={1,2,3,4,5,6,7,8,9,0};
      printf("%d\n",sizeof(arr));
      fun(arr);
      return 0;
  }
运行结果

在这里插入图片描述

  • 总结
    只要是函数传参,传的是数组都要发生降维问题,降维为指针
    所有的数组(不管是几维的数组)都可以看成是一维数组

C程序认为的内存空间的布局规律

在这里插入图片描述
数组开辟空间时一次开辟数组长度的空间,然后按照a[0]—a[9],从小到大依次分配空间a[0]在低地置端。(在栈中储存)

  • 每次调用函数就形成栈帧,函数返回释放栈帧.
#include<stdio.h>
int main()
{
    char* pstr = "hellow bit.";  
    printf("%s\n",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("%d\n",sizeof(arr));
    	
    	q=s;
    }
    int main()
    {
    	int arr[10]={0,1,2,3,4,5,6,7,8,9};
    	printf("%d\n",sizeof(arr));
    	fun(arr);
    	printf("%s\n",q);
    	return 0;
    }

在这里插入图片描述

#include<stdio.h>
    char *q=NULL;
    void fun(int arr[])
    {
    	char a[]="hellow bit.";
    	printf("%d\n",sizeof(arr));
    	
    	q=a;
    }
    int main()
    {
    	int arr[10]={0,1,2,3,4,5,6,7,8,9};
    	printf("%d\n",sizeof(arr));
    	fun(arr);
    	printf("%s\n",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)=%d\n",sizeof(arr));
    	printf("sizeof(arr+1)=%d\n",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= %p\n",arr);
           printf("   &arr= %p\n",&arr);
           printf("  arr+1= %p\n",arr+1);
           printf(" &arr+1= %p\n",&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=%d\n",**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代表的就是其指向的内容

  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值