数组作函数参数的退化问题

  昨天真是气得慌,刚写完这个,提交的时候,浏览器竟然崩了,大半夜的第二天又有课,于是就拖到今天才写了。

  续借前题,我之前说过写完内存四区之后,会开始讲关于指针的问题,然而一看题目似乎与指针并没有多大关系,而我说的内存四区估计大家也是看到一脸懵,这一点我确实没怎么写好,但是正如定义那样,写代码的时候,大家可以在脑海中建立内存四区模型。

 为什么我要这么说,因为什么是指针?指针是通过存储的地址来操作内存空间,也就是说我们想要操作这块内存空间才使用了指针,这样的话,我们总得知道我们操作的空间属于哪一块吧!或者说它有什么属性吧!要不然我们连指针指向哪里都不知道,我们要这指针又有什么用!

  指针:通过储存的地址来操作内存空间

  先来个例一

  #include <stdio.h>

  #include <string.h>

  #include <stdlib.h>

  void disrtibution_01(int a)// 空函数是不用return的

  {

    a = 100;

  }

  void distribution_02(int *a)

  {

    *a = 200;//同过指针改变实参的值

  }

  int main()

  {

    int a = 10;

    disrtibution_01(a);//将数值传递给形参

    printf("%d\n",a);//我们发现数值并未改变 a = 10

    distribution_02(&a);//将地址传递给指针

    printf("%d\n",a);//我们发现数值改变 a = 200

    return 0;

  }

  在这里我们发现,同样是void型函数:仅仅想通过传递值来改变实参是无法做到的,然而却可以通过差传递地址将值改变,也就是指针可以通过操作内存空间来修改里面的数值,先这样理解:指针是可以改变所指向的变量的值的;

  例子二:

  

  #include <stdio.h>
  #include <string.h>
  #include <stdlib.h>

  void sortArray(int a[4])//排序
  {
  int i = 0;
  nt j = 0;
  int tmp = 0;//辅助变量

  printf("sizeof(a):%d\n",sizeof(a));//a占4个字节
  //冒泡排序法
  //由小到大排序
  for(i = 0; i < 4; i++)
  {
    for(j = i+1; j < 4; j++)
    {
    if(a[i] > a[j])//如果前面的数大于后面的数则交换 a[i] 和 [j] 比较
     {
       tmp = a[i];//将a[i] 的值赋给tmp
      a[i] = a[j];//将后面较小的数值赋给前面
      a[j] = tmp;//将前面较大的数值赋给后面
     }

    }
   }

  }

  void sortArray2(int a[],int num)
  {
  int i = 0;
  int j = 0;
  int tmp = 0;//辅助变量

  printf("sizeof(a):%d\n",sizeof(a));//a占4个字节
  //冒泡排序法
  //由大到小排序
  for(i = 0; i < num; i++)
  {
  for(j = i+1; j < num; j++)
    {  
    if(a[i] < a[j])//如果前面的数大于后面的数则交换 a[i] 和 [j] 比较
    {
    tmp = a[i];//将a[i] 的值赋给tmp
    a[i] = a[j];//将后面较大的数值赋给前面
    a[j] = tmp;//将前面较小的数值赋给后面
    }

    }
  }
}

 

  void sortArray3(int *a,int num)
  {

  int i = 0;
  int j = 0;
  int tmp = 0;//辅助变量

  printf("sizeof(a):%d\n",sizeof(a));//a占4个字节
  //冒泡排序法
  //由小到大排序
  for(i = 0; i < num; i++)
  {
  for(j = i+1; j < num; j++)
  {
    if(a[i] > a[j])//如果前面的数大于后面的数则交换 a[i] 和 [j] 比较
    {
    tmp = a[i];//将a[i] 的值赋给tmp
    a[i] = a[j];//将后面较小的数值赋给前面
    a[j] = tmp;//将前面较大的数值赋给后面
    }

  }
  }
}

 

  void printfArray(int a[4])//打印数组
  {
    int i = 0;
     for(i = 0 ; i < 4; i++)
     {
    printf("%d ",a[i]);
    }
    printf("\n");

  }

 

 

  int main()
  {
  int i = 0,j = 0;
  int tmp = 0;
  int num = 0;

  int a[] = {22,33,4,333};//一维数组 4 * 4 = 16

  num = sizeof(a)/sizeof(a[0]);//数组的下标是从0开始的

  printf("sizeof(a):%d\n",sizeof(a));//计算分配的内存空间大小 16

  sortArray(a);
  printf("第一个函数排序打印:");//4 22 33 333
  printfArray(a);

  sortArray2(a,num);
  printf("第二个函数排序后打印:");//333 33 22 4
  printfArray(a);

  sortArray3(a,num);
  printf("第三个函数排序后打印:");//4 22 33 333
  printfArray(a);


  system("pause");
  return 0;
  }

   在这里为了给数组里的值排序我用来三个函数sortArray(int a[4]), sortArray2(int a[],int num),  sortArray3(int *a,int num);

  我们发现sortArray(int a[4])和例子一里的disrtibution_01(int a)似乎很相似,但是这里对数组的排序竟然成功了;这说明 这个int a[4]和int a是不同的;

  首先看main函数int a[] = {22,33,4,333};//一维数组里我们分配了 4 * 4 =  16 字节的内存空间

  但是在三个子函数中我们都发现,他们所占的内存只有4 个字节,这里我们要知道所有的指针只占四个字节的内存空间,不管是一级指针还是十级指针,所以数组作参数时我们发现,他们所占的内存空间和指针是一样的;也就是说调用的时候并没再次给他们分配 16 字节的内存空间;

  而且我们发现三个函数参数是这样变化的:int a[4] ==>int a[] ==>int *a;而且它们都运行成功了:

  于是我们就得出这么一个结论:

  数组作参数时编译器自动将它们退化为了指针;而指针通过地址找到内存空间并对其进行操作;

  可能很多人看完之后还是很不解,这是很正常的,我刚开始学的时候也是这样,于是通过不断的翻阅资料,不断的敲代码,才开始逐渐理解,指针被称为c的灵魂,自然不可能是这么一言两语就能说完,所以接下来的日子我会把我对指针的见解逐渐分享给大家,希望可以互相交流,共同提高;

posted @ 2017-09-20 15:37  SmartGame  阅读(513)  评论(0编辑  收藏  举报