zoukankan      html  css  js  c++  java
  • c提高第四课

    1、一维数组的初始化

    int a[] = { 1, 3, 5 }; //3个元素
    int b[5] = { 1, 2, 3 }; //a[3], a[4]自动初始化为0
    int c[10] = { 0 }; //全部元素初始化为0
    memset(c, 0, sizeof(c)); //通过memset给数组每个元素赋值为0

    2、数组类型

    int a[] = { 1, 3, 5 }; //3个元素
    a: 数组首行首元素地址,一级指针
    &a: 整个数组的首地址,二级指针


    首行首元素地址和首行(整个一维数组)地址值虽然是一样,但是它们的步长不一样

    a+1: 跳过1元素,一元素为4字节,步长4个字节
    &a+1: 跳过整个数组,整个数组长度为 3*4 = 12,步长 3 * 4 = 12
    
    sizeof(a): 传参为:数组首行首元素地址,测数组(int [3])的长度,3 * 4 = 12
    sizeof(a[0]): 传参为:数组首元素(不是地址),每个元素为int类, 4字节
    sizeof(&a):传参为:一维数组整个数组的地址(首行地址),编译器当做指针类型,4字节

    (重要)首行地址 --> 首行首元素地址(加*)

    &a:首行地址
    *&a -> a : 首行首元素地址

    //数组也是一种数据类型,类型本质:固定大小内存块别名
    //由元素类型和内存大小(元素个数)共同决定 int a[5] int[5]
    //可以通过typedef定义数组类型

    //有typedef:类型
    //没有typedef:变量
    typedef int ARRARY[5]; //定义了一个名字为ARRARY的数组类型,[5]表示步长
    //等价于typedef int (ARRARY)[5];

    //根据数组类型,定义变量
    //ARRARY的位置替代为d,去掉typedef,int d[5]
    ARRARY d; //相当于int d[5];

    3、数组指针变量(它是指针变量,指向数组的指针)

    //定义数组变量
    int a[10];
    
    //有typedef:类型
    //没有typedef:变量

    1、根据数组类型,定义指针变量,数组指针变量

    typedef int ARRARY[10]; //定义了一个名字为ARRARY的数组类型
    //等价于typedef int (ARRARY)[10];
    
    ARRARY *p;    //数组指针变量
    
    //编译会有警告,但不会出错,因为 a 和 &a的值一样
    //就算p = a这样赋值,编译器内部也会自动转换为 p = &a
    //不建议这么做
    p = a; 
    
    //p 指向a数组,指向一维数组的指针
    p = &a; 
    
    //如何操作数组指针变量 p
    int i = 0;
    for (i = 0; i < 10; i++)
    {
    (*p)[i] = i + 1;
    //p = &a
    //*p -> *(&a) -> a
    //(*p)[i] -> a[i]
    }


    2、直接定义数组指针变量(常用)
    //()[]同级,从左往右看
    //()有*,它是一个指针,[]代表数组
    //指向数组的指针变量,[]中的数字代表指针+1的步长
    int(*p)[10];

    //p 指向a数组,指向一维数组的指针
    p = &a;


    3、先定义数组指针类型,再根据类型定义指针变量(常用)
    //数组指针类型,加上typedef
    typedef int(*Q)[10];
    Q p; //根据类型定义变量,p是数组指针变量
    p = &a; //p指向数组a

    4、多维数组本质
    1)二维数组初始化

    int a1[3][4] = {
    {1, 2, 3, 4},
    {5, 6, 7, 8},
    {9, 10, 11, 12}
    };
    
    int a2[3][4] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 };
    
    int a3[][4] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 };

    2)内存中并不存在多维数组,多维数组在内存中都是线性存储

    int a[3][5] = { 0 };
    int *b = (int *)a;//转换成一维
    int i = 0;
    for(i = 0; i < 15; i++){
      printf("%d ", b[i]);
    }

    3)多维数组名


    //学会类比
    int b[5] = {0};
    b: 首行首元素地址, +1,跳 4 个字节
    &b:首行地址,+1,跳 4*5 = 20个字节

    //二维数组实际上就是 N 个一维数组
    //把二维数组第一个[]的值看做标志位,0 -> 2
    //第0个一维数组a[5] -> 第2个一维数组a[5]
    int a[3][5] = { 0 };
    a:
    二维数组首元素地址
    代表首行地址,相当于一维数组整个数组的地址,相当于上面的 &b,本来就是一个二级指针

    //(重要)首行地址 --> 首行首元素地址(加*)
    *a:首行首元素地址,相当于一维数组首元素地址,相当于上面的 b

    a + i -> &a[i]: 第i行地址

    //(重要)某行地址 --> 某行首元素地址(加*)
    *(a+i) -> *&a[i] -> a[i]: 第i行首元素地址

    //第i行j列元素的地址,某行首元素地址 + 偏移量
    *(a+i)+j -> a[i]+j -> &a[i][j]: 第i行j列元素的地址

    //第i行j列元素的值,第i行j列元素的地址的基础上(加 *)
    *(*(a+i)+j) -> a[i][j]: 第i行j列元素的值

    int a[3][5] = { 0 };
    sizeof(a): 二维数组整个数组长度,4 * 3 * 5 = 60 //只要是数组名就是测整个数组长度
    sizeof(a[0]):a[0]为第0行首元素地址,相当于测第0行一维数组的长度:4 * 5 = 20
    sizeof(a[0][0]):a[0][0]为第0第0列元素(是元素,不是地址),测某个元素长度:4字节

    4)多维数组名,实际上是一个数组指针,指向数组的指针,步长为一行字节长度

    int a[3][5] = { 0 };

    //定义一个数组指针类型的变量
    int(*p)[5];

    //编译会有警告,但不会出错,因为 a 和 &a的值一样
    //但是&a代表整个二维数组的首地址
    //就算p = &a这样赋值,编译器内部也会自动转换为 p = a
    //不建议这么做
    p = &a;   

    //a 本来就是第0个一维数组整个数组的地址,所以,无需加&
    p = a;


    5)二维数组做形参的三种形式
    //一维数组做函数参数退化为一级指针
    //二维数组(多维数组)做函数参数,退化为数组指针

    int a[3][5] = { 0 };

    void print_array1(int a[3][5]);

    //第一维的数组,可以不写
    //第二维必须写,代表步长,确定指针+1的步长 5*4
    void print_array2(int a[][5])

    //形参为数组指针变量,[]的数字代表步长
    void print_array3(int (*a)[5]);

    //a+1和二维数组的步长不一样
    //这里的步长为4
    //上面二维数组的步长为 5 * 4 = 20
    void print_array3(int **a); //err


    5、指针数组(它是数组,每个元素都是指针)
    1)指针数组的定义
    //指针数组变量
    //[]优先级比*高,它是数组,每个元素都是指针(char *)
    char *str[] = { "111", "2222222" };

    char **str = { "111", "2222222" }; //err


    2)指针数组做形参
    void fun(char *str[]);
    void fun(char **str); //str[]  ->  *str

    3)main函数的指针数组
    //argc: 传参数的个数(包含可执行程序)
    //argv:指针数组,指向输入的参数

    int main(int argc, char *argv[]);
    
    : demo.exe a b test
    int argc = 4
    char *argv[] = {"demo.exe", "a", "b", "test"}
     

    笔记
    ===================================================================================
    1、
    typedef int A[10];//A:数组类型
    A b;//int b[10],数组类型变量,普通变量
    A *p;//数组类型定义数组指针变量

    typedef int (*p)[10];//数组指针类型
    P p;//数组指针变量

    int (*q)[10];//数组指针变量

    2、
    int a[][4] = { 1,2,3,4,5,6,7,8,9,10,11,12 };
    //a: 代表第0行首地址
    //a+i :代表第i行首地址
    //*(a+i)    -> a[i]: 代表第i行首元素地址
    //*(a+i)+j -> &a[i][j] :代表第i行第j列元素地址
    //*(*(a+i)+j) ->a[i][j] =第i行第j列元素的值

     

    二维数组数组名:第0行首地址
    a+i:第i行首地址
    要想把首地址转化首元素地址,加*:*(a+i)
    要想得到某个元素地址,加偏移量: *(a+i)+0, *(a+i)+1, *(a+i)+j
    ->&a[i][0] &a[i]+1 &a[i][j]
    要想得到某元素的值,是这个元素的地址基础上加*
    *(*(a+i)+j) -> *&a[i][j] ->a[i][j]

    int (*q)[10];//数组指针变量

  • 相关阅读:
    图片反转效果
    css实现三角效果
    漂亮的阴影效果
    css名词解释
    偷学来的资料
    Git、GitHub、GitLab三者之间的联系以及区别
    分模块、分工程管理
    Spring AOP面向切面编程
    为什么要用存储过程,什么时候要用存储过程,存储过程的优点
    Spring扫描组件的使用详解
  • 原文地址:https://www.cnblogs.com/zyqy/p/9449554.html
Copyright © 2011-2022 走看看