精华内容
下载资源
问答
  • 指针与函数 指针作为函数的参数 指针最为函数的返回值 案例 ...结构体数组如果你有5个学生的信息你会怎么 结构体数组如果你有5个学生的信息你会怎么 结构体指针 结构体的嵌套当我们在为结构体定

    指针与函数

    指针作为函数的参数
    1. 函数有多个返回值时
    2. 地址传递
    3. 如果函数的参数是一个指针,函数希望传递给调用者一个信心,保证不会修改值,就可以加一个 const 修饰
    指针最为函数的返回值
    1. 当然可以作为返回值.
    2. 函数中的数组作为返回值,如果是在函数内创建的数组,函数执行完后就会回收,返回的地址虽然可以访问,数据就不一定在了.
    3. 你返回的指针指向的变量一定要保证函数结束后,那个空间没被回收.
    4. 如果一定要返回一个指针,就将空间申请在堆区.

      int* test();
      {
      int* arr = calloc(3,sizof(int));
      *arr = 10;
      *(arr+1) = 20;
      *(arr+2) = 30;
      
      return arr;
      }
      调用者:
      int* arr = test();
      
    5. 调用者用完后一定要

      free(arr);
      
      • 注意:返回值可以返回局部变量的值,但不能返回局部变量的地址!
    案例

    返回一个1-7数字对应的英文星期几

        char* getWeekDay(int day);
        //如果返回值是字符串,那么类型就是 char 指针
        {
            switc(day)
            {
                case 1:
                    return "Monday";
            }
        }
    

    另一种写法

    //返回字符指针.
    char* weekDay = "未知";
    switch(day)
    {
        case 1:
            weekDay = "Monday";
            break;
    }
    return weekDay;
    调用
    char* str = getWeekDay(1);
    //申请在常量区的空间是不会回收的,程序结束才会回收.
    

    指向函数的指针

    程序在运行的时候,会将程序加载到内存
    1. 程序中主要有代码/指令.
    2. 代码段中主要存储程序的代码
    3. 程序的代码就包括函数
    4. 既然函数要存储到内存中,就肯定需要空间,有空间就有地址,有地址就可以声明一个指向函数的指针!
      那么调用函数就有了两种方式.
    5. 直接用函数名
    6. 用指向函数的指针.声明语法(有点复杂)并不是任意函数都可以指向的

    a. 只能指向没有返回值并且没有参数的函数

    返回值类型(*指针名)([参数列表]);
    void(*pFunction)();
    表示声明了一个指向函数的指针,名字叫做 pFunction.
    

    b.只能指向返回值为 int 类型,并且有两个整形的参数的函数.

    int(*pfun)(int num1,int num2);
    

    c.初始化

    1. 取到符合指针条件的函数地址
    2. 函数的名称就代表函数的地址.
    printf("%p",test);
    //千万不要加小括号,加了就是执行函数,拿到返回值.
    
    3. 将地址赋给指针变量,直接将符合条件的函数的名称赋给这个指针.
    void(*pfun)() = test;
    //pFun指针就指向了 test 函数.
    

    d.调用

    //简写
    pFunc();
    //原样.
    (*pFunc)();
    

    e.小技巧

    拷贝函数头
    int test(int num1,int num2);
    
    删除函数名,用小括弧代替,里面写上*加指针名
    int (*pFunction)(int num1,int num2);
    
    后面加赋值符号,将原来的函数名(函数的地址)赋值给这个指针
    int (*pFunction)(int num1,int num2) = getSum;
    
    然后直接写指针名加括号调用
    int num = pFunction(10,20);
    

    结构体

    存一个人的年龄你会怎么存?

    int age = 18;
    占用了4个字节,浪费
    
    一个人的年龄0-200之间,没有负数,一个字节就够了
    unsigned char age = 18;
    

    保存一个人的身高.一个班级的平均分.
    //一个变量就是来存储一个数据描述这个数据的.

    • 如果让你保存一个学生呢?

    使用我们之前任何一个变量都不行
    1. 姓名 字符串
    2. 年龄 int
    3. 性别 char
    4. 成绩 double

    我们要表示一个学生,就需要多个普通的变量的和起来描述.

    • 怎么合起来?

    exa: 数组

    数组要求元素的类型一致,所以拜拜

    exa: 一种有几种普通变量合成的一个大变量.

    没有这种类型的变量,但是我们可以自己定义这样的数据类型.

    指定这个数据类型的变量是由哪些小变量合成的
    • 使用结构体来创建新类型的数据

      struct 新类型名称
      {
      数据类型1 变量名称1
      数据类型2 变量名称2
      数据类型3 变量名称3
      }

      创建了一个数据类型,由 char 指针 int 变量,float 联合而成.
      struct Student
      {
      char* name;
      int age;
      int score
      float height;
      };
      创建了类型,保存在代码段.

    • 刚刚只是创建了一个类型,指定了由哪些数据类型组成,还没有变量.

      再声明刚才创建的结构体类型的变量
      struct 结构体名称 变量名;
      struct Student stu;
      //这个结构体大变量是由结构里规定的小变量组合而成的.
      stu 结构体变量的类型是 struct Student.

    • 结构体变量的初始化(赋值)

      stu.name = “jack”;
      stu.score = 100;
      stu.age = 17;
      stu.height = 189.8;
      结构体名称.成员名 = 数据;
      printf(“姓名:%s 年龄:%d 成绩:%d 身高:%.2f\n”,stu.name,stu.age,stu.score,stu.height);

    • 总结,什么时候定义结构体
      1. 我们要保存一个数据, 但是发现这个数据是一个大数据,由其他小数据联合起来组成的
      2. 保存一个坐标点
      3. 一个图片的长和宽等等,使用数组每个变量没有名称,结构体更容易让人理解
      4. 注意的几个小问题

      1. 一定要先使用结构体定义新的类型,然后才可以根据这个类型声明这个类型的变量.
      2. 结构体是一个变量.所以可以批量声明

        struct Student xiaoHua,jin,meiMei,liLei

      3. 结构体的命名规范,要求每个单词首字母大写
      4. 声明结构体同时声明变量

      struct Computer
      {
      char* cpumodel;
      int menSize;
      char* brand;
      } iMac,lenvol,hp,dell;

      1. 匿名结构体

      struct
      {
      char* barnd;
      char* color;
      int price;
      }fengshan1;
      //只能在声明结构体的同时就命名
      //声明后不能单独的声明这个结构体的变量

    结构体变量的初始化
    刚才我们是先声明变量再使用点. 一个个的为成员赋值,你是不是觉得很麻烦?
    • 在声明结构体变量的同时,怎么为结构体变量的成员初始化呢?

      //最常用的
      struct Student xiaoHua = {“小花”,18,89}; *
      //或者初始化一部分
      struct Student liLei = {“李雷”};
      //还可以指定成员初始化
      struct Student jim = {.name = “基姆”,.age = 17,.score = 100};

    • 结构体变量的初始值

      1. 声明一个结构体变量,如果没有为成员赋值,成员就是垃圾值.
      2. 只要在声明结构体变量的同时,初始化一个成员,其他成员的值就是0;
    • 结构体的作用域.

      1. 结构体是定义在函数内部的,那么结构体类型只能在函数的内部使用
      2. 如果希望所有函数都可以使用,就定义在最顶上
      3. 一般情况下我们的结构体类型都是定义在函数的外面的,让所有的函数来用

    结构体之间的相互赋值

    1. 相同结构体类型的变量之间绝对是可以相互赋值的

      struct Student xiaoMing = {“小明,19,100};
      struct Student xiaoHua = xiaoMing;

    2. 赋值原理

      将源结构体当中的成员变量的值拷贝一份给目标结构体的变量.

    3. 结构体变量赋值是值传递

      结构体数组

    如果你有5个学生的信息你会怎么做?

    声明5个结构体?

    struct Student s1 = {"小明1",16,56};
    struct Student s2 = {"小明2",18,77};
    struct Student s3 = {"小明3",19,98};
    struct Student s4 = {"小明4",16,67};
    struct Student s5 = {"小明5",17,100};
    
    • 其实可以用结构体数组来管理

      声明:
      struct 结构体类型名称 数组名称[数组长度];
      struct Student students[5];
      表示我们声明了一个长度为5的结构体数组
      数组名叫 students
      数组的元素的类型的 struct Student

    结构体数组

    如果你有5个学生的信息你会怎么做?

    声明5个结构体?

    struct Student s1 = {"小明1",16,56};
    struct Student s2 = {"小明2",18,77};
    struct Student s3 = {"小明3",19,98};
    struct Student s4 = {"小明4",16,67};
    struct Student s5 = {"小明5",17,100};
    
    • 其实可以用结构体数组来管理

      声明:
      struct 结构体类型名称 数组名称[数组长度];

      1. 表示我们声明了一个长度为5的结构体数组
      2. 数组名叫 students
      3. 数组的元素的类型的 struct Student
        struct Student students[5];
        students[0] = s1;
        students[1] = s2;
        students[2] = s3;
        students[3] = s4;
        students[4] = s5;
    • 遍历

      一个 for 循环就可以搞定了
      for(int i = 0;i < 5;i++)
      {
      printf(“姓名:%s 年龄:%d 成绩:%d\n”,
      students[i].name,
      students[i].age,
      students[i].score
      );

    • 结构体数组的初始化

      1. 刚才那种用下标一个个初始化的方式仍然是很傻的方式.(以下的方法可以认为是给部分指定的元素初始化)

      struct Student students[5];
      students[0] = (struct Student){“小明1”,16,56};
      students[1] = (struct Student){“小明2”,18,100};
      students[2] = (struct Student){“小明3”,19,10};
      students[3] = (struct Student){“小明4”,21,100};
      students[4] = (struct Student){“小明5”,13,3};
      注意: 当我们为结构体数组的元素赋值的时候.如果直接使用大括弧来初始化.
      就必须要前面加1个小括弧,来告诉编译器我们的给的数据类型.

      1. 在声明结构体数组的同时就初始化(按顺序初始化)

      //5 可以省略
      struct Student students[5] =
      {
      {“小明1”,16,56},
      {“小明2”,18,100},
      {“小明3”,19,10},
      {“小明4”,21,100},
      {“小明5”,13,3}
      };

    • 计算长度

      怎么计算总长度?
      int len = sizeof(students)
      len == 80
      在计算每个元素的字节数,用总长度一除
      int len = sizeof(students)/sizeof(struct Student);
      //students是数组名,student 是结构体类型名称

    结构体指针

    struct student
    {
        char* name;
        int age;
        int score;
    };
    struct Student xiaoMing = {"小明",18,100};
    xiaoMing 是一个变量.类型是 sturct Student 类型的
    既然是变量就有地址,有地址就有指针.
    

    格式

    struct 结构体类型名称* 指针名;
    struct Student* pStu; 
    //声明了一个能指向 struct Student 类型的指针变量.
    

    初始化

    取出结构体变量的地址
    &xiaoMing;
    
    赋值给指针变量
    pStu = &xiaoMing;
    struct Student* pStu = &xiaoMing;
    

    操作

    (*结构体指针名).成员
    (*pStu).name = "jack";
    (*pStu).age = 18;
    (*pStu).score = 99;
    
    第二种方式
    pStu->name = "jack";
    pStu->age = 18;
    代表把18 赋给 pStu 指向的 age 成员.
    

    结构体的嵌套

    当我们在为结构体定义成员的时候. 发现某个成员也是1个大数据 需要其他的几个小变量合起来描述,那么这个时候你就可以再定义1个数据类型.来表示这个类型.
    struct Date
    {
        int year;
        int month;
        int day;
    };
    //在 Person 结构体中加入一个 Date 结构体保存出生年月日.也可以加入农历出生年月日.
    struct Person
    {
        char* name;
        int age;
        double money;
        struct Date birthday;
    };
    
    struct Person xiaoMing = {"曾凡怡",22,100000000.0,{1994,2,23}};
    printf("姓名:%s--年龄%d--财产:%lf--生日:%d--%d--%d",
            xiaoMing.name,
            xiaoMing.age,
            xiaoMing.money,
            xiaoMing.birthday.year,
            xiaoMing.birthday.month,
            xiaoMing.birthday.day
            );
    

    结构体作为函数的参数

    1. 结构图是一种数据类型,当然也可以作为函数的参数和返回值.
    2. 结构体作为参数传值是值传递

      struct Student
      {
      char *name;
      int age;
      int score;
      };
      void panDuanXueSheng(struct Student stu)
      {
      if(stu,score >= 60)
      {
      printf(“恭喜%s 你及格了.\n”,stu.name);
      }
      else
      {
      printf(“抱歉%s 你落榜了”,stu.name);
      }
      }
      这个函数接收的是值,函数内部如果想更改实参变量的值是不行的.

    3. 如果你就是希望函数的内部可以修改实参的值,就使用指针

      void jiaFen(struct Student* stu)
      {
      stu->score = 100;
      }

    4. 结构体作为返回值

      struct getAStudent()
      {
      struct Student s1 = {“rose”,21,100};
      return s1;
      }

    5. 返回一个结构体指针

      include

    枚举

    限定一个变量中只能给指定的几个值,除此之外都不行.C 语言默认没有提供限定取值类型的变量,我们就自己定义一个,枚举就支持我们新创建一个这种类型.
    enum 新类型的名称
    {
        限定取值1,限定取值2,限定取值3,......
    };
    enum Direction
    {
        East,
        South,
        West,
        North
    };
    1. 表示新创建了一个数据类型,名字叫做 enum Direction.
    2. 可以声明这个类型的变量.
    3. 这个变量中就只能存储这其中指定的任意一个.
    
    • 声明

      enum 枚举类型名称 变量名;
      enum Direction dir;

      1. 表示声明了一个变量,名字叫 dir
      2. 类型是 enum Direction.
      3. 只能存储这个枚举类型限定的取值之一.

      enum Direction dir = East;

    • 注意

      1. 枚举的作用域在定义的函数内部使用,希望所有的都是用就定义在最顶部.
      2. 每一个 枚举值/枚举项 都有一个对应的整形的数,默认从0开始,依次递增.%d 打印就看得到

      这个枚举有多大?
      int len = sizeof(dir); 无论是什么类型的枚举变量都是4个字节.
      枚举变量当中(dir),真正存的就是对应的整形得数.

      printf(“%d\n”,dir);

      1. 所以也可以给枚举变量赋值一个整形的数据…
      2. 虽然我们可以给整数,但我们并不会这么做.代码的可读性会很差.
      3. 给1和 South 完全等价
      4. 手动指定对应的数.

      enum Direction
      {
      East = 10,
      South = 20,
      West = 30,
      North = 40
      };
      East 对应的整形的数就是10.

    • 一些规范

      1. 枚举类型的命名规范:

      首字母大写.每个单词的首字母也大写

    • 枚举值的命名规范:
      以枚举的类型开头.这样你敲出前面几个字符就可以出现提示,枚举中有哪些值枚举.

    typedef

    作用:

    1. 为一个已经存在的数据类型取一个别名.
    2. 如果我们想要使用这个类型,就直接使用别名.
      语法格式:
    typedef 已经存在的数据类型 别名;
    typedef int itheima;
    为 int 数据类型取了一个别名,叫做 itheima
    int == itheima;//这两个名字现在就完全等价了.
    typedef char* string;
    string name = "rose";
    //一秒钟让你的 C 语言有 string 类型
    

    我们前面了解的 size_t 其实就是 typedef 定义的 unsigned long
    3. 什么时候用?
    当数据类型很长的时候 unsigned long long int 这种,定义以后用起来就很方便了.
    4. 还有呢?
    struct Student 好长好难写. typedef 他,写在外面最顶上. typedef struct Student Student;
    5. 先声明再重命名,也可以声明的同时就重命名.

    typedef struct Student//这个 Student 是结构体名称
    {
        char* name;
        int age;
        int score;
    }Student;//这个 Student 是重命名后的数据类型名称.
    

    6. 声明匿名结构体的同时就为结构体取一个短别名 *

    上面的第一个 Student 删掉,就是一个匿名结构体,后面一个数据类型的 Student 就成了这个匿名结构体的短名.***
    7. typedef 为枚举取一个短别名

    enum Direction
    {
        DirectionEast
    };
    type enum Direction Direction;
    
    声明同时改名
    type enum Direction 
    {
        DirectionEast
    }Direction;
    //其实....使用上面这种方式和匿名结构体一样,第一个 Direction 也不用写了.
    
    展开全文
  • 40) C语言数组做函数参数 41)c语言之递归 字符串和字符串函数 42)c语言之字符串I/O 43) C语言之字符串输入/输出 44) C语言之字符串处理函数 文件操作 45) C语言之文件是什么 46) C语言之用fopen() ...
  • 自学去c语言视频教程

    2013-12-03 19:24:57
    40) C语言数组做函数参数 41) C语言之函数之递归详解 字符串和字符串函数 42) C语言之字符串表示和字符串I/O 43) C语言之字符串输入/输出 44) C语言之字符串处理函数 操作文件 45) C语言之文件是什么 46) C语言...
  • C语言】函数传参

    2020-01-07 20:13:50
    文章目录1、函数参数传递的三种方式1.1、值传递1.2、引用传递1.3、地址传递2、传递结构体3、传递数组3.1、数组做为参数传递3.2、不允许将数组做返回值4、形参为空5、不定长参数表 1、函数参数传递的三种方式 1.1...


    1、函数参数传递的两种方式

    1.1、值传递

    #include <stdio.h>
    /* 变量x、y为Swap函数的形式参数 */
    void Swap(int x, int y)
    {
        int tmp;
        tmp = x;
        x = y;
        y = tmp;
        printf("x = %d, y = %d\n", x, y);
    }
    int main(void)
    {
        int a = 10;
        int b = 20;
        /*变量a、b为Swap函数的实际参数*/
        Swap(a, b);
        printf("a = %d, b = %d\n", a, b);
        return 0;
    }
    

    输出:
    x = 20, y = 10
    a = 10, b = 20

    1.2、地址传递

    #include <stdio.h>
    void Swap(int* px, int* py)
    {
        int tmp;
        tmp = *px;
        *px = *py;
        *py = tmp;
        printf("*px = %d, *py = %d\n", *px, *py);
    }
    int main(void)
    {
        int a = 10;
        int b = 20;
        Swap(&a, &b);
        printf("a = %d, b = %d\n", a, b);
        return 0;
    }
    

    输出:
    *px = 20, *py = 10
    a = 20, b = 10

    1.3、C中没有引用传递

    如果在.C文件中出现函数参数为引用则出现莫名其妙的错误

    void InsertSort(SqList &L);

    报错error C2143: syntax error : missing ‘)’ before ‘&’
    C++中才有引用传递,C中是没有引用传递的

    2、传递结构体

    3、传递数组

    3.1、数组做为参数传递

    • 数组做为函数的参数需要传递两个参数
      • 数组的地址
      • 数组的元素个数
    #include <stdio.h>
    void print(int a[],int n)
    {
            int i;
            for(i=0;i<n;i++)
                    printf("%d ",a[i]);
            printf("\n");
    }
    int main()
    {
            int a[3]={1,2,3};
            int b[5]={1,2,3,4,5};
            print(a,3);
            print(b,5);
            return 0;
    }
    

    3.2、不允许将数组做为返回值

    只需要向函数中传递数组,不需要返回数组。不允许也无意义。
    因为函数中操作的形参数组值发生了改变,实参也会跟着变化。

    #include <stdio.h>
    void print(int a[],int n)
    {
            int i;
            for(i=0;i<n;i++)
                    printf("%d ",a[i]);
            printf("\n");
    }
    void add(int a[],int n)
    {
            int i;
            for(i=0;i<n;i++)
                    a[i]<<=1;
    }
    int main()
    {
            int a[5]={1,2,3,4,5};
            print(a,5);
            add(a,5);//对数组a里的值进行数值变化
            print(a,5);//再输出数组a的值已发生了变化
            return 0;
    }
    

    输出:
    1 2 3 4 5
    2 4 6 8 10

    4、形参为空

    • 形参为空表示,传参不定,可传可不传。
    • 传什么值都能编译通过
    #include <stdio.h>
    #include <string.h>
    char *getStr()//形参为空表示,传参不定,
    {
            return "Hello world";
    }
    
    int main()
    {
            char str[100]="";
            strcpy(str,getStr(1,"aa"));
            printf("%s\n",str);
            return 0;
    }
    
    • 如果不允许传参,形参可以为void
    char *getStr(void)
    {
    	//... ...
    }
    

    5、不定长参数表

    如C语言内置函数printf

    int printf(const char *format,...);
    

    5.1、不定长参数表的原理

    不定长参数表依赖三个函数。这三个函数的头文件是<stdarg.h>,其实下面的三个函数都是一个宏定义(macro)。
    这三个函数是:

    void va_start(va_list ap, last);
    type va_arg(va_list ap, type);
    void va_end(va_list ap);
    

    5.2、va_list

    va_list型的变量,这个变量是指向参数的指针

    5.3、va_start

    初始化定义的va_list变量,使其指向第一个可变参数的地址。

    5.4、va_arg

    返回可变参数,va_arg的第二个参数是你要返回的参数的类型(如果多个可变参数,依次调用va_arg获取各个参数)

    • 第二个参数如果传char或short会被提升为int
    • 第二个参数如果传float会被提升为double

    5.5、va_end

    结束可变参数的获取

    5.6、不定长参数举例

    例一:

    #include <stdio.h>
    #include <stdarg.h>
    int max(int n, ...)
    {
        va_list v;                      //定义va_list变量
        va_start(v, n);                 //使v指向第一个参数的地址
        int i;
        int maxvalue = va_arg(v, int);//获得第一个参数
        
        for (i = 1; i < n; i++) {
            int data = va_arg(v, int);//依次获取参数列表中的每个参数
            if (data > maxvalue)
                maxvalue = data;       
        }
        va_end(v);
        return maxvalue;
    }
    
    int main()
    {
        printf("%d\n", max(2, 2, 5));
        printf("%d\n", max(3, 4, 1, 6));
        return 0;
    }
    

    例二:

    #include <stdio.h>
    #include <stdarg.h>
    void print(int n, ...)
    {
        va_list v;
        va_start(v, n);
        int i;
        for (i = 0; i < n; i++)
        {
            puts(va_arg(v, char*));
    
        }
        va_end(v);
    
    }
    int main()
    {
        print(2, "hello", "word");
        return 0;
    }
    
    

    输出:
    hello
    world

    展开全文
  • 40) C语言数组做函数参数 41) C语言之函数之递归详解 字符串和字符串函数 42) C语言之字符串表示和字符串I/O 43) C语言之字符串输入/输出 44) C语言之字符串处理函数 操作文件 45) C语言之文件是什么 46) ...
  • C语言复习

    2020-11-20 18:52:36
    重新复习了一下C 当年读书没好好学,现在就花时间重新打基础。 1.数据类型 int char long int 2.signed unsigned 3.程序的结构 顺序,选择,循环 4.数组(一维数组,二维...定义结构体,然后实例化结构体,再调用 ...

    重新复习了一下C
    当年读书没好好学,现在就花时间重新打基础。
    1.数据类型 int char long int
    2.signed unsigned
    3.程序的结构 顺序,选择,循环
    4.数组(一维数组,二维数组,多维数组)
    5.函数(定义,格式,参数,调用,返回值)
    6.指针,指向数据的指针,指向函数的指针,指向数组的指针,指向指针数据的指针
    其中指针最为重要,需要反复看。
    目前工作写的函数,都是用指针做参数。
    定义结构体,然后实例化结构体,再调用

    展开全文
  • C语言讲义.doc

    2018-01-27 10:41:43
    2.4 指针数组做为MAIN函数的形参 65 3 内存管理 65 3.1 作用域 65 3.1.1 auto自动变量 65 3.1.2 register寄存器变量 65 3.1.3 代码块作用域的静态变量 66 3.1.4 代码块作用域外的静态变量 66 3.1.5 全局变量 66 ...
  • 数组 结构体 共用体 B.整型 数组 指针 C. 整型 实型 字符型 D.指针 逻辑型 空类型 13. 一个C语言程序是从( A )开始执行。 A. main函数 B.包含文件的第一个函数 C. 程序中的第一个语句 D.程序中的第一个...
  • 10.1.5 结构体数组应用举例 84 10.2 typedef说明一种新类型名 85 习题 87 第11章 指针、链表和动态内存分配 89 11.1 地址和指针 89 11.2 指针变量的定义和指针变量的基类型 90 11.3 指针变量的赋值及基本操作 ...
  • 以下内容为平时工作中的一些学习笔记,没有来得及排版整理,请谅解!指针就是地址,是可以直接引用... 指针(基本指针类型、函数指针、结构体指针、数组指针等) 用函数指针参数的好处 举例:Process ( int x , int

    以下内容为平时工作中的一些学习笔记,没有来得及排版整理,请谅解!

    指针就是地址,是可以直接引用的,在c语言当中地址分为:(可直接引用)

    1. 指针

    2. 函数名

    3. 数组名

    4. 结构体名

    指针用法1:作为函数参数
    函数的参数类型与函数返回值类型:

        1.   基本数据类型
    
        2.   指针(基本指针类型、函数指针、结构体指针、数组指针等)
    

    用函数指针做参数的好处 举例:

    Process ( int xint yint ( *fun )())
    {
            int result ;
    result = ( *fun )( xy );
    }

    好处:有了函数指针做参数,只需要修改 Process 的函数指针就可以实现 一个函数指向多个功能函数 ,简单高效!**

    基础知识补充: 指针,找到根源!程序的快捷方式!

    使用指针的好处:

    1. 有效地表示复杂的数据结构;

      2 有效而方便地使用数组;

    2. 动态地分配存储器,直接处理内存地址;

    3. 在调用函数时还能输入或返回多于 1 个的变量值;

    4. 可以使程序简洁、紧凑、高效。

    /*
    如果你有一个或两三个保险柜 , 那么你可以将这几个保险柜的钥匙都放在身上 .~ 如果你有几百个保险柜 , ~ 你还愿意都将钥匙放在身上吗 ? 呵呵 , 肯定不愿意的吧 . 那么怎么办 ?~ 哈哈 , ~ 对拉 ! ~ 就是将保险柜钥匙贴上标签放到一个抽屉里面 , 而你身上只带着这把抽屉的钥匙 . ~~ 需要的时候就拿钥匙开抽屉罗 . 指针也就是这样啦 . 指针存放的是地址 ( 也就是保险柜的钥匙 ). 数据 ( 也就是保险柜的物品 ) 是通 ~ 过地址打开的 !
    */

    在数据传递时,如果数据块较大(比如说数据缓冲区或比较大的结构),这时就可以使用指针传递地址而不是实际数据,即提高传输速度,又节省大量内存。

    1. 指针(间接访问方式): 地址就是指针!

    定义:专门用来存放地址的变量称为指针变量。指针本身(的地址)是不变的,变的是它存放的地址。

    与其它变量的区别:存的是地址,使用时与其它变量的使用方法一样。

    运算符区分:

    ” * “的作用:

    1. 用于定义时,表示申请一个”指针变量”( 用于存取地址 )如: int *p; // 定义一个指针变量

    2. 用于运算时,表示它所指向的变量的值( 取出被指向的变量的值 ),可直接代表真正的值。

    ” & “的作用:取地址运算符。一般用它来取地址给指针变量。

    如: int *ap, int a;
    
        ap = &a;//ap 指向变量 a        
    

    指针使用步骤:

    ○ 1 定义: int *ap ;

    ○ 2 指向: ap = &a;//ap 指向变量 a

    ○ 3 使用 x=*ap ;

    指针一般可以指向哪些类型?

    ○ 1 变量

    ○ 2 函数

    ○ 3 结构体

    ○ 4 数组

    *p 指向谁,就代表谁!

    结构体:把多个不同类型的变量结合在一起形成一个组合型变量,称为构造变量,简称结构体。

    1. 定义结构体的类型

    形式:

    struct 结构名

    {

    结构成员说明;

    } 变量名 ;

    如:

    struct date{
    
            int monthint dayint year ;
    
    }date1 , date2 ;
    1. 定义结构体类型变量
    struct date{
    
            int monthint dayint year ;
    
    } ;

    struct date date1,date2;/* 定义结构的变量名 */

    1. 结构体类型变量的引用:

    ○ 1. 结构不能作为一个整体参加赋值、存取和运算 ; 也不能整体地作为函数的参数,或函数的返回值。

    对结构所执行的操作 ,只能用” & “运算符取结构的地址 ,或对结构变量的成员 分别加以引用 。

    如: UartTx_Put_EffectiveFrame(&UartTxBuf[BufIndex]); // 引用结构体数组

    引用的方式:结构体变量名 . 成员名;如 date1.year =2003 ;

    ” . “” -> “符号是成员运算符,优先级最高。

    “.” 用于非指针成员

    ” -> “只能用于指针成员,但” . “也可以用于指针成员。

    ○ 2. 如果结构体变量的成员本身又属于一个结构类型变量,则要用若干个” . “一级一级找到最低一级的成员,只有最低一级的成员才能参加赋值、存取和运算。

    1. 指向结构体类型数据的指针 (可作为函数参数传递)

    ○ 1. 指向结构体数据的指针 就是该结构体数据在内存中的 首地址 。

    ○ 2. 指向一个结构数组的指针 就是本结构体 数组的起始地址 。

    指向结构体类型数据的指针定义的一般形式:

    struct 结构体类型名 * 指针变量名; 如: struct msg1 *msg ;

    或者

    struct{

    结构体成员说明;

    }* 指针变量名;

    定义一个结构体指针后需要:

    1. 赋值

      方法 1: 可以给 p 分配一段内存空间,并使其指向此空间:
      
      p=(struct abc *)malloc(sizeof(struct abc));
      
      p->a = 1;
      
      方法 2 :可以让 p 指向一个已存在的内存空间:
      
      struct abc temp;
      
      p=&temp;
      
      p->a = 1; 
      

    结构体数组:

    赋初值:

    例如一个struct student {char na[5];float grrade} , 它可以这样初始化 struct student stu[2]={“hjk”,4},{“jkl”,45};

    方式一:

       struct student stu[100] = {0};
    

    方式二:

       struct student stu[100];
    
       memset( stu, 0, sizeof(stu) );
    

    方式三:

       struct student stu[2]={"hjk",4},{"jkl",45};
    
    1. 函数指针 ( 专门用来存放函数入口地址 ) 调用函数

    一个函数在编译时 C 编译器会给它分配一个入口地址。这个 入口地址就称为函数的指针 。可以用一个指针变量指向函数,然后通过该指针变量调用此函数。

    函数指针的定义: int (p)(int); / 函数指针变量定义 */

    1 .函数指针定义

    函数类型 ( * 指针变量名) ( 形参列表 ) ;

    ” 函数类型 ” 说明函数的返回类型,由于 “()” 的优先级高于 “*”, 所以指针变量名外的括号必不可少,后面的 ” 形参列表 ” 表示指针变量指向的函数所带的参数列表。

    例如:

    int (*f)(int x);

    double (*ptr)(double x);

    指向 :指针 = 函数名 如: p=factorial ; /* 函数指针变量 p 指向 factorial() 函数 */

    调用 :( * 指针)(参数)如: c= ( p)(5 ) ;/ 用指针变量 p 调用 factorial 函数 */

    函数指针归纳如下:

    ○ 1 指向函数的指针变量的一般形式定义为:

    函数返回值类型( * 指针变量名)(函数形参表 …… ) ;

    定义的函数指针变量:把哪个函数地址赋给它,则它就指向哪个函数。在一个程序中,通过不同的赋值,一个函数指针变量 可以先后指向不同的函数 。

    ○ 2 在给函数指针变量赋值时, 只需给出函数名而不必给出参数 ,如 p= factorial;// 只给地址即可

    ○ 3 调用:只需将( *p ) 代替函数名即可 ,在( *p )之后的括号中可根据需要 写实际参数。

    如 c= ( p )( 5 ) ; / 调用 p 指向的函数 factorial ,实参为 5 ,返回值赋给 c */

    ○ 4 对指向函数的指针变量进行诸如 p+n , p++ 和 p- - 的运算是没有意义的。

    总结: 函数指针,指针名替函数名,且运算无意义!

    1. 数组、指针作为函数的参数

    1 )用数组作为函数的参数

    ○ 1 数组名作函数参数时,应该在调用函数和被调用函数中 分别定义数组。

    ○ 2 实参数组与形参数组的类型一致

    ○ 3 实参数组与形参数组的大小可以一致,也可以不一致。( 不看形参,看实参 ) C 编译器对形参数组的大小不作检查,只是将实参数组的地址传给被调函数。

    总结: 数组指针做参数,调用被调都定义,不看形参看实参。

    1. 用指向函数的指针变量作为函数的参数

    参数为指针函数,执行指向函数,传递参数与执行函数

    即,传指针,指向谁,执行谁!

    1. 用指向结构的指针变量作为函数的参数

    问: C 语言不允许整体引用结构体变量名,那么如何将一个结构变量的值从一个函数传递给另一个函数呢?有两种方法:

    1 . 直接引用成员。 像用变量作为函数的参数一样,直接引用结构体变量的成员作为参数。

    2 .传送结构体地址。 用指向结构变量的指针变量作实际参数,将结构变量的地址传递给被调用函数的形式参数。

    即,传指针,指向谁,执行谁!

    9.1 返回指针的函数

    函数可以返回: int 、 char 、 float 等,同样也可返回指针型数据,即 返回一个数据的地址。

    形式:

    返回值类型 * 函数名(参数表)

    例如: int A ( x , y ) {…..}/ 函数体前带” * “返回指针 */

    A 为函数名,调用它后可以得到一个指向 int 型数据的指针(地址)。

    与指针函数对比

    函数指针的定义: int p() ; / 函数指针变量定义, 函数定义时带” * “为指针函数 */

    9.2 定义返回函数指针的函数: return_type(function(func_parameter_list))(parameter_list) 定义了一个函数 function ,该函数的参数列表是 (function_patameter_list) ,返回类型是一个函数指针,这个函数指针的原型是 return_type()(parameter_list) 。

    例: int (*add1(int a,int b))(int,int) 此处:此函数的函数主体为 add1,add2 函数作为 add1 的形参,返回值为一个函数指针。 注:返回的函数的形式必须为 int funcname(int,int)

    可以用 typedef 来简化定义: // 此函数等效于上面函数 typedef int (*funcp)(int)(int); // 定义整型函数指针 funcp add1(int a,int b);

    总结:

    传指针,指向谁,代表谁,执行谁!

    返指针,指向谁,代表谁,执行谁!

    1. 数组指针和指向数组的指针变量

    1 ) 数组指针:所谓数组的指针,就是数组的起始地址(数组名)。

    例如: a[10]; a 就是数组指针(因为数组名是地址)

    2 ) 指向数组的指针变量:用来存放一个数组的起始地址(指针)。

    int a[10];

    int app;/ 与一般指针变量一样形式 */

    app=&a[0];

    1. 数组

    定义:一组 同类型且有序数据 的集合叫做数组。定义一个数组时, C 编译器就会在系统的存储空间中开辟一个区域,用于存放该数组的内容。数组就包含在这个由 连续存储 单元组成的模块的存储体内。

    二维数组:存取顺序是:按行存取,先存取第一行元素的第 0 列, 1 列, 2 列 ……. ,直到第一行的最后一列;然后返回到第二行开始,再取第二行的第 0 列, 1 列, ….. 以此类推。

    总结:

    1. 函数指针:指向函数的指针

    ○ 1 定义: 函数类型 ( * 指针变量名) ( 形参列表 ) ;

    例如:
    
    int (*p)(int x);
    

    ○ 2 指向: p= factorial;// 只给地址即可

    ○ 3 调用: p ( j ) ;

    1. 返回指针的函数 :返回值是指针(函数的地址)

    2. 定义:

      int A()/ 返回指针的函数,称为指针函数,是函数 */

      {

    int (*p)(int);// 定义一函数指针

    p =max;// 指向 max ( int x )函数

    return p;// 返回函数的地址

    }

    int (point)(int);/ 可以指向函数的指针,称为函数指针,是指针 */

    point=A();// 返回函数指针(地址)给 point 。

    包含头文件 #include “stdlib.h”

    *malloc(unsigned int size); // 动态分配内存

    free(demo1);// 释放指针内存

    举例:

    demo1=(struct DEMO *)malloc(sizeof(struct DEMO));// 分配内存

    free ( demo1 ); // 释放内存

    使用函数指针的好处:

    1 、 回调函数。

    2 、实现面向对象中多态的功能。

    结构体函数指针 举例:

    struct DEMO
    
    {
    
        int x;
    
        int y;
    
        int (*func)(int,int); 
    
    };
    
    
    
    
    int add2(int x,int y)
    
    {
        return x+y;
    }

    struct DEMO demo;/* 构造一个结构体 */

    demo.func=add2;/* func 指向 add2 函数 */

    p->fun();/* 执行结构体中函数 */

    指向数组的数组的指针(指向地址的地址)双指针

    1.被指的数组指针本身应该是个双维数组

    code BYTE **code Vmcd_Str[] = 
    
    {
        Txt_loading_s,        //STR_VMCD_LOADING=0, //加载中
        Txt_reading_s,
    };
    
    BYTE  *ptxt; 
    ptxt = Vmcd_Str[0][1];
    展开全文
  • 指针函数就是一个函数,因为返回值是个*类型 指针数组 一个数组,里面存的是带*号类型 结构体指针 星号*详解,返汇编代码 char* p1 p1 里面存储的是一个地址 p1 p1前面加号就是获取p1里面存储地址对应的值 两种...
  • 1.4.2 C语言简史及特点.................................................................................20 1.4.3 C程序示例及组成.............................................................................
  • void是无类型(0字节),常用于函数返回值,不可以定义变量,因为其类型不开辟内存空间; void* 是个指针类型(4个字节)可以定义变量,但是不能对其进行初始化操作。 (signed) char(1个字...
  • 征服指针(C)

    2018-01-20 13:00:44
    3.2.5 C语言中不存在多维数组! 116 3.2.6 函数类型派生 117 3.2.7 计算类型的大小 119 3.2.8 基本类型 121 3.2.9 结构体和共用体 122 3.2.10 不完全类型 123 3.3 表达式 125 3.3.1 表达式和数据类型 125 ...
  • C学习深入学习总结

    2017-11-03 16:59:17
    C语言各种常用关键字详细解释学习,都是总结面试,都是比较好的笔试题。 1 变量 3 1.1 全局变量,局部变量,,常量分别保存在内存中的什么地方? 3 1.2 不同类型的变量,你是否知道其作用域? 3 1.3 全局变量和局部...
  • 07_数组做函数参数退化问题剖析_传智扫地僧 08_数据类型基础提高 09_数据类型引申和思考 10_变量本质剖析和内存四区模型引出_传智扫地僧 11_c的学习重理解到位_对初学者_传智扫地僧 12_直接通过内存标号操作内存空间...
  • Linux C 编程一站式学习.pdf

    千次下载 热门讨论 2010-11-24 01:27:27
    但并不是说只要具有高中毕业的数学水平就足够程序员了,只能说看这本书应该没有问题,数学是程序员最重要的修养,计算机科学其实就是数学的一个分支,如果你的数学功底很差,日后还需恶补一下。 具有高中毕业的...
  • 6. Wings支持所有C语言的数据类型(基础类型,结构体,指针,数组,枚举等)以及高层级数据结构。 例如链表的分析和对应的驱动和数据表格框架的生成。 7. Wings生成的代码与人工写的非常相近,可读性强,自带注释和...
  • Wings支持所有C语言的数据类型(基础类型,结构体,指针,数组,枚举等)以及高层级数据结构。 例如链表的分析和对应的驱动和数据表格框架的生成。 7. Wings生成的代码与人工写的非常相近,可读性强,自带注释和...
  • 1、本系统采用一个结构体数组,每个数据的结构应当包括:学号、姓名、M门课程名称。 2、本系统显示这样的菜单: 请选择系统功能项: a、 成绩录入 b、 成绩显示 c、 成绩保存 d、 成绩排序 e、 成绩修改(要求先输入...
  • 13.第十三章 文件.txt

    2019-11-08 16:33:27
    FILE是在stdio.h头文件中定义的一个结构体,用来保存文件信息。 fopen函数用来打开一个文件,其调用的一般形式为: 文件指针名=fopen(文件名,使用文件方式); 其中: ·“文件指针名”必须是被说明为...
  • 有人说,C++是C语言的继承者;有人说,C++是一种面向对象的思维方式;有人说,C++很好很强大;更有人说,不要迷恋C++,C++只是一个传说。可以说,这些答案都从某个侧面回答了“C++是什么”,但是又都不全面。  在...
  • 黑马安卓52期视频教程

    热门讨论 2015-06-24 22:15:48
    07_开启activity获取返回值(重点) 08_请求码和结果码的作用(重点) 09_activity的生命周期(重点) 10_读文档查看activity的生命周期 11_横竖屏切换的生命周期(重点) 12_任务栈的概念、singletop启动模式 14_...
  • C 标准I/O库粗略实现

    2020-12-08 19:40:13
    数组末尾之后的第一个元素(即&arr[n],或者arr + n)的指针算术运算可以正确执行。下面的例子也是上述的一种应用场景: <pre><code>C int a[10] = {1,2,3,4,5,6,7,8,9,10}; ...
  • 在C++中,有两种给出注释的方法:一种是延用C语言方法,使用"/*"和"*/"括起注释文字。另一种方法是使用"//",从"//"开始,直到它所在行的行尾,所有字符都被作为注释处理。 2-8 什么叫做表达式?x = 5 + 7是一个...

空空如也

空空如也

1 2
收藏数 26
精华内容 10
关键字:

c语言结构体数组做返回值

c语言 订阅