zoukankan      html  css  js  c++  java
  • C语言 数组做函数参数退化为指针的技术推演

    //数组做函数参数退化为指针的技术推演
    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    
    //一维数组做函数参数退化为指针的技术推演
    
    void printfA(char * strarr[3]);
    //计算机中,数组都是线性存储,二维数组元素也是一个个的排列的
    //例如: 1,2,3,4,5,6,7,8,9    像这组数据  我们可以认为是一维数组   int a[9]={1,2,3,4,5,6,7,8,9};
    //也可以认为是二维数组 int b[3][3]={1,2,3,4,5,6,7,8,9};
    //所以计算机并不清楚数组名的步长是多少  就是  a+1移动多少个字节 或者 b+1 移动多少个字节
    //这就需要程序员去告诉计算机  数组名的步长是多少
    //对于本题 void printfA(char * strarr[3]);  数组做函数参数  该数组是一个一维数组   数组元素类型是 char *
    //那么数组strarr的步长应该是 sizeof(char *)  也就是4个字节   
    //这么来说  我们只需要告诉计算机   你跳4个字节  就OK了  
    //所以技术推演为printfB
    void printfB(char * strarr[]);
    //因为计算机根本不关心你有多少个元素  是3个  还是30个  与计算机没关系  是程序员需要关心的(这就是数组越界问题)
    //函数参数 char * strarr[] 同样告诉计算机  我是一个一维数组  数组元素是 char * 类型
    //那么数组strarr的步长还是 sizeof(char *)  也就是4个字节   
    //那么我们继续推演   既然计算机只需要确定  该数组每次移动的步长是 4个字节就好
    //那么void printfC(char ** strarr);这么写也是可以的   strarr是个指针  strarr里的值指向一个类型是 char *的变量
    //步长只与指针的值有关 ,因此strarr的 步长是 sizeof(char *)  也就是4个字节   
    //所以C语言的开发人员就做了优化  printfC  (与我没关系  设计C语言的就是这么优化的)
    void printfC(char ** strarr);
    //char * strarr[3]做参数退化为char ** strarr)  有2个好处   
    //好处1:复制一个一维数组char * strarr[3]  比复制一个指针char ** strarr  会耗费更多的内存空间
    //char * strarr[3] 需要耗费 sizeof(char *) * 3 =12 个字节的内存空间 ;
    //而char ** strarr需要耗费 sizeof(char **) = 4 个字节的内存空间   ;
    //节约了内存  和创建 数组时的资源消耗
    //好处2:减少了无用解析 ;对于char * strarr[3]   元素个数3  没用,
    //这是个一维数组  这个信息没用  ,因为遍历数组的时候从首地址开始遍历, 只要给计算机个首地址就行  
    //计算机从首地址向后遍历   无需知道他是什么   只需要知道每次的步长是多少就好了
    
    
    
    //二维数组做函数参数退化为指针的技术推演
    void printfD(int arr[3][4]);
    //对于二维数组,C语言编译器同样需要知道 数组名arr的步长 就是在遍历的时候 每次计算机改移动多少个字节
    //那么首先  我们应该确定数组名arr 到底是个什么类型 
    //数组名 是数组首元素的指针 (我自己的推论)  那么二维数组 可以想象成一维数组   只是这个一维数组的每个元素比较特殊,还是一个一维数组
    //那么根据推论  数组名arr的类型是一个一维数组的指针   一维数组是这样定义的  typedef int Myarr[4];
    //一维数组指针的类型定义是这样的 typedef int (* PMyarr)[4]; 
    //一维数组指针的变量是这么定义的int (* pmyarr)[4]; 
    //所以数组名arr的类型是 int (* PMyarr)[4];  因为指针的步长与指针所指向的内存空间相关
    //arr指向的是一个typedef int Myarr[4]类型的数组,这个数组有4个元素,每个元素都是int类型
    //由此得出arr这个一维数组指针的步长是  sizeof(int)*4 = 16;
    //由 一维数组的推演可知  数组元素的个数对C语言编译器并不重要 二位数组的元素可以看作一维数组  
    //推演出 void printfD(int arr[][4]);
    void printfE(int arr[][4]);
    //又因为  C语言编译器  只需要知道  首地址  和步长  所以  可以用 int (*p)[4] 来代替 int arr[][4]
    void printfF(int(*arr)[4]);
    
    
    //综合以上分析,导出结论   数组做函数参数退化为指针,指针的类型就是数组名的类型
    
    void main(){
        char * strarr[3] = { "123", "456", "789" };
        int arr[3][4] = { 0 };
        system("pause");
    }
  • 相关阅读:
    泛型与非泛型
    C# 调用CMD,执行DOS命令
    数据库设计随笔(ZZ)
    关于三层开发(zz)
    三层架构学习(转)
    Node.js & child_process All In One
    HTML5 Canvas Tag Cloud All In One
    macOS & VSCode terminal show current git branch All In One
    飞书 excel 固定列 All In One
    git diff one of committed file All In One
  • 原文地址:https://www.cnblogs.com/zhanggaofeng/p/5377768.html
Copyright © 2011-2022 走看看