枚举

没有使用枚举的情况为

  • 代码

    #include<stdio.h>
    const int Yello = 0;
    const int Green = 1;
    const int Red = 2 ;  //枚举比const int 方法好用
    int main(int argc, char const*argv[]){
      int color = 1;
      switch(color){
      case 0:
          printf("Yello");
          break;
      case 1:
          printf("Green");
          break;
      case 2:
          printf("Red");
          break;
      }
      return 0;
    }
  • 枚举是一种用户定义的数据类型,它用关键字enum以如下语句来声明

    enum 枚举类型的名字{名字0 , 名字1, 名字2...};
  • 枚举类型名字通常并不真的使用,要用的是大括号里的名字【常量符号】,类型为int,值则依次为0到n
    操作

    #include<stdio.h>
    enum Color {Yello, Green ,Red , Numbers};
    void print(enum Color t,int i){
      printf("%d\n",t); // enum Color t 为代号 即int
      char* colorNames [Numbers] = {"Yello","Green","Red"}; 
      if(i >=0 && i < Numbers ){
          printf("%s\n",colorNames[i]);
      }
      else printf("unknown\n");
    }
    int main(int argc, char const*argv[]){
      enum Color c = Red;
      int myLike = 0;
      print(c,myLike);
      return 0;
    }

    枚举量可以指定值

  • 枚举比宏好,因为枚举有int 不过使用起来并没有java那么好用!!!

结构

复合数据类型

  • 定义方式
    struct date{
      int month;
      int day;
      int year;
    }; //<---分号
  • 使用
    #include<stdio.h>
    struct date{ //可以在函数内 或者函数外
      int month;
      int day;
      int year;
    };
    int main(int argc, char const*argv[]){
      struct date today ; //!!!!
      today.year = 2020;
      today.month = 1;
      today.day = 2;
      printf("%i-%i-%i",today.year,today.month,today.day); //%i 在scanf里会识别八进制、16进制输入,并转换成10进制
      return 0;
    }

声明结构的形式 定义 初始化

  1. p1 p2 都是一种point的结构的两个变量,里面有x和y
    struct point{
     int x;
     int y;
    };
    struct point p1 ,p2;
  2. p1 p2 都是一种无名的结构的两个变量,里面有x和y
    struct {
     int x;
     int y;
    }p1 ,p2; //这个结构仅能够给p1 p2 使用
  3. p1 p2 都是一种point的结构的两个变量,里面有x和y
    struct point{
     int x;
     int y;
    }p1 , p2;
  • 初始化
    #include<stdio.h>
    struct date{//结构类型
      int month;//结构变量
      int day;
      int year;
    };
    int main(int argc, char const*argv[]){
      struct date today ; 
      today.year = 2020;
      today.month = 1;
      today.day = 2;
      struct date myday = {.year = 2020,.month = 1, } ; 
      printf("%i-%i-%i\n",today.year,today.month,today.day); //%i 在scanf里会识别八进制、16进制输入,并转换成10进制
      printf("%i-%i-%i\n",myday.year,myday.month,myday.day); 
      return 0;
    }
    //2020-1-2
    //2020-1-0

结构[类型可以不同]和数组[相同类型]有点像
可以整个结构可以做赋值、取地址也可以传递给函数参数

  • p1 = (struct point){5,10};强制类型转换 p1.x = 5 ;p1.y = 10;
  • p1 = p2 ; 【数组不可以】 相等后 修改一个 并不会给另外一个造成影响

结构指针

  • 和数组不同【数组为首位置的地址】,结构变量的名字并不是结构变量的地址,必须使用&运算符
    struct date * pDate = &today 
  • 案例
    #include<stdio.h>
    struct date{
      int month;
      int day;
      int year;
    };
    int main(int argc, char const*argv[]){
      struct date today ; 
      today.year = 2020;
      today.month = 1;
      today.day = 2;
      struct date myday = today; 
      printf("%p\n",myday);
      myday.day = 3;
      printf("%p\n",myday);
      printf("%i-%i-%i\n",myday.year,myday.month,myday.day); 
      printf("%p\n",today);
      printf("%i-%i-%i\n",today.year,today.month,today.day); //%i 在scanf里会识别八进制、16进制输入,并转换成10进制
      return 0;
    }
    //0x200000001
    //0x300000001
    //2020-1-3
    //0x200000001
    //2020-1-2

结构作为函数参数

  1. 可以当作参数的值传入函数
  2. 这个时候在函数内新建一个结构变量,并复制调用者的结构的值 <-- 克隆品
  3. 也可以返回一个结构
  4. 这与数组不同
    #include<stdio.h>
    struct date{
     int month;
     int day;
     int year;
    };
    //传入函数中的结构变量 在函数中可以创建一个临时的结构变量 然后把这个结构返回给调用者
    struct date funtion(struct date day){
     printf("%i-%i-%i\n",day.year,day.month,day.day); 
     day.day++;
     printf("%i-%i-%i\n",day.year,day.month,day.day); 
     return day; //返回传入指针 NICE!!!!
    }
    int main(int argc, char const*argv[]){
     struct date today ; 
     today.year = 20120;
     today.month = 1;
     today.day = 2;
     printf("%i-%i-%i\n",today.year,today.month,today.day); 
     struct date myday = funtion(today);
     printf("%i-%i-%i\n",today.year,today.month,today.day); 
     printf("%i-%i-%i\n",myday.year,myday.month,myday.day); 
     return 0;
    }
    //20120-1-2
    //20120-1-2
    //20120-1-3
    //20120-1-2
    //20120-1-3
  • 赋值 scanf("%i %i %i",&today.year,&today.month,&today,day);

传结构的指针好处大于直接传整个结构 因为要花费拷贝的过程!!! 浪费资源

  • 现在用指针的话代码如下 p是指针
    用-> 表示指针所指的结构变量中的成员
    struct date *p = &myday;
    (*p).month = 12; //符号多
    //等价于
    p->month = 12; 
  • 参与赋值
    struct point* getStruct(struct point *p){// 返回出来可以串入其他函数的运算
      ...
      scanf("%d",&p->x); //p是一个指针 p->x 表示指针对应的结构变量  然后& 取出它的地址
      scanf("%d",&p->y);
      printf("%d %d " ,p->x ,p->y);
    }

结构其他应用

  • 结构数组
    struct date dates [100] = {{...},{...}};
  • 结构含结构
    struct date point { struct date time , struct date day}
  • 四种形式是等价的
    如果有变量定义:
      struct rectangle r, *rp;
      rp = &r;
    那么下面的四种形式是等价的: 
      r.ptl.x ;  //r不是指针 
      rp->ptl.x ; //ptl是指针
      (rp -> ptl).x ;
      (r.ptl).x;
      //但没有rp -> ptl -> x  因为ptl 不是指针  即是结构本身

自定义数据类型

typedef 目标一大串 命名为xxx

  • 目的是取别名 typedef int Length; Length就是int!!!

  • 作用于结构 将整个结构替换为
    Date day <--原来的--- struct date day;

    #include<stdio.h>
    typedef struct date{ //有无结构名字date 已经不是很重要了
      int month;
      int day;
      int year;
    } Date;
    
    int main(int argc, char const*argv[]){
      Date day = {1,3,2020};
      printf("%i-%i-%i",day.year,day.month,day.day);
      return 0;
    }
  • 字符串
    typedef * char[10] Strings

  • 节点

    typedef struct node {
      int data;
      struct node *next;
    }Node;

联合 union

跟struct 非常相似,但所有成员一起用一份空间

  • 代码
    union Ant{
      int i ; 
      char c ;
    }ant;
  • sizeof(union ...) = sizeof(每个成员)的最大值
    所有成员共享一个空间,同一时间只有一个成员是有效的,union的大小是其最大的成员
    初始化:对第一个成员做初始化
    union Ant{
      int i ;  //1234 十六进制0000 04D2   计算机地位在前 D204 0000 ,c的取值就是int 的数据
      char c[sizeof(int)] ; 一块空间 sizeof(int)若等于四个字节,则i跟c 一起用这个空间
    }ant;
  • 应用:得到整数内部的字节 double内部的字节 中间的笔记