• C语言复合数据类型


           C语言数据类型非常丰富,其中结构体的使用非常广泛,也有一点复杂,这一讲我们主要学习结构体的使用方法,同时也会学习到联合、枚举以及typedef的使用,因为结构体最为复杂,使用最广,所以我们主要学习结构体。

    struct结构体的定义和初始化

    //例:
    struct student{
    char name[100];
    int age;
    };
    int main(){
    struct student st;
    //定义了一个student类型的结构体,名字叫做st,存放在栈里边
    st.age =20;
    strcpy(st.name,”liudehua”);
    struct student st1 ={“zhzdu”,40};
    //定义结构体变量,同时初始化结构体变量
    struct student st1 ={.age =40,.name=”zxjiifuhg”};
    //定义结构体变量,同时初始化结构体变量,使用这种方式可以改变初始化顺序
    struct student st1 ={“zhzdu”};
    //定义结构体变量,同时初始化结构体变量,不初始化的结构体变量则默认为0
    };

    结构体的对齐说明

         结构体在内存中总是对齐的,一个结构体成员变量总是以最大的那个元素作为对齐单位。

    struct A{//8字节,a1后面空着3个字节,a2占4个字节
    char a1; 
    int a2;
    }
    struct A1{//8字节,a1后面空着一个字节,然后a3占两个字节,a2占4个字节
    char a1;
    short a3;
    int a2;
    }
    struct A2{
    char a[10];
    int b; 
    }

           如果结构体出现数组,则以数组中的具体每个成员大小为对齐标准,如果变量结构体中的所有成员都是一种类型,那么结构体在内存中就基本和一个数组类似。结构体变量的地址就是它首元素的地址。

    结构体元素的位字段

          为了节省内存空间,结构体变量允许使用为声明,例子如下:

    struct A2{//一共占1字节
    unsigned char a:2;//a只有两个bit
    unsigned char b:4;  //b只有4个bit
    }

    结构体数组

    struct A2{
    char name[20];
    unsigned char age; 
    unsigned char sex;
    }
    void main(){
    struct A2 st[3];//定义一个结构体数组,有3个成员,每个成员都是struct结构体变量
    }

           CPU处理int相比其它基本数据类型效率是最高的,但是int比char要多占内存.

    冒泡排序结构体数组

           首先要学会使用冒泡排序,然后根据结构体某个成员大小之间作比较,再根据冒泡排序交换结构体中的各个成员来排序,具体的实现方法可自行实现。

    结构体嵌套

           结构体内部可以有其它结构体,其本质和结构体没有太多区别。

    struct A{
    char a1;
    short a2;
    };
    
    struct B{
    struct A a;//这里是一个结构体的嵌套
    char a3;//上面结构体变量作为一个整体存在,a3 不可能补到结构体A a2的后面去,它一定是一个单独的对齐单位。
    int b;
    };
    struct D{};//D结构体不含有任何结构体变量,这个语法在C语言是不合法的,在C++里是合法的

            结构体的赋值其实就是内存的拷贝

    struct A{
       char a1;
       short a2;
    };
    struct A st1={s ,s};
    struct A st2=st1;
    //通过指针访问结构体成员
    struct A  * p=&st1;
    //(*p).a1 =12;这种写法与下面写法作用相同,但下面写法更直观
    p->a1 = 12;

    通过指针访问结构体数组

               这个和通过指针去访问数组是类似的,这儿就不详细介绍了

    void main(){
    struct A2 st[3]={0};
    struct A2 *p=st;
    p[1].name = “zcxc”
    }

    结构体中的数组成员和指针成员

    struct man{
    char * name;
    int age;
    };

           结构体拷贝的时候存在浅拷贝与深拷贝;浅拷贝之间只是成员之间的粗暴赋值,解决不了结构体中存在指针时,两个指针成员之间只是简单的地址赋值,当一个结构体变量指针成员释放空间时,另一个结构体变量指针成员访问的空间也就消失了,两结构体变量之间相互影响很大。深拷贝则是存在指针变量时,首先为指针变量各自分配空间,然后再进行拷贝,每个结构体指针变量指向的的空间时相互独立的。

    堆中创建结构体变量

    struct man{
    char  name[20];
    int age;
    };
    struct student{
    char * name;
    int age;
    }
    int main(){
    struct man st;//name在栈里边
    struct man *st1 = malloc(sizeof(struct man));//name在堆里边
    struct man *p = malloc(sizeof(struct student));//name在堆里边
    p->name = malloc(20);
    strcpy(p->name,”lfsdi”);//申请一个堆空间,st1->name在堆里,但是一个野指针
    st1->age = 20;
    free(p->name);
    free(p);//如果结构体变量里含有指针,注意free的先后顺序,如果先free p,则p堆已经释放了,就找不到p->name的首地址
    }

    函数的参数为结构体变量

    struct man{
      char  name[20];
      int age;
    };
    printf_student(struct student st){//st是形参,函数调用的时候,在栈里面有一个浅拷贝的过程,如果里边某个成员为数组较大,会出现一个数组拷贝的过程,会消耗大量时间,不利于优化程序
      printf(“%s,%d\n”,st.name,st.age);
    }
    printf_student(const struct student *st) {//st =&st //只是一个简单的结构体地址赋值,效率远远高于上面的,形参很少直接用一个结构体变量,一般放结构体指针
      printf(“%s,%d\n”,st->name,st->age);
    }

    联合体

           联合union是一个能在同一个存储空间存储不同类型的数据,联合体所占的内存长度等于其最长成员的长度,所以代码效率很高。联合体虽然有多个成员,但同一时间只能存放其中一种。

    union A{
    int a1;
    short a2;
    char a3;
    char *p;
    };//只占4个字节
    int main(){
    union A a;
    a1 =1;
    a3 =10;
    a1 =0; //之后a.a3的值为0
    a.p = malloc(10);//假设这块堆的内存编号为0x12345C
    a.a1 = 0;//p的值也成了0
    free(a.p);
    return 0;
    }

    枚举类型

         可以使用枚举声明代表整数常量的符号名称,关键字enum创建一个新的枚举类型,实际上enum常量是int类型的,可以增加代码的可读性。

    struct A2{
    char name[20];
    unsigned char age; 
    unsigned char sex;
    }
    
    enum color{red,blue,yellow,green,black};
    enum sex {man,woman};
    void main(){
    struct A2 st;
    enum sex s;
    s =man;
    strcpy(st.name,”znfysry”);
    st.sex = man;//man就是一个整形的常量,不能做左值,常量也不能取地址
    st.age = 0;
    }

           每一个枚举都有默认值0,1, 2,3,4,5,6……… 可以自己设置每个成员的值,enum color{red = 100,blue =12,red = 58,yellow,black,white};100,12,58,59,60,61.....,100 在系统内是由CPU产生的一个立即数,不能取地址, “hello”在内存的常量区里,可以取地址,int a =100;//CPU生成一个立即数,在栈中分配一个4个字节的空间,然后把这个空间的值设置为100,enum在编译完成后只是一个不存在于内存中的立即数,不能取地址。

    typdef数据类型

          typdef数据类型是一种高级数据类型,它能使某种类型创建自己的名字。仅限于数据类型,不能是表达式或具体的值。

    struct student{
        char name[20];
        unsigned char age; 
        unsigned char sex;
    }
    typedef struct student M;//M就类似于int,就是一种数据类型
    typedef unsigned char BYTE;//多了一种数据类型叫byte.可以提高代码的维护性
    int main(){
    M m;
    BYTE a;
    return 0;
    }

            typdef数据类型不是一种必须使用的数据类型,但是使用typedef主要目的是为了让程序的可读性更高,方便代码的维护,在代码十分庞大的时候这种数据类型就显得十分必要。

    #ifndef UNICODE  //方便维护代码
    typedef wchar_t TCHAR
    #else
    typedef char TCHAR
    #endif
    void main(){
    TCHAR a1;
    }
  • 相关阅读:
    Codeforces Round #362 (Div. 2) C
    poj1655 树重心
    poj1985 树直径
    Codeforces Round #403 (based on Technocup 2017 Finals)
    uva 10054 The necklacr
    bfs codeforces 754B Ilya and tic-tac-toe game
    矩阵快速幂专题
    CodeForces 863E Turn Off The TV 思维,扫描线
    CodeForces 803F Coprime Subsequences 莫比乌斯,容斥
    CodeForces 803C Maximal GCD 思维
  • 原文地址:https://www.cnblogs.com/latencytime/p/10167509.html
Copyright © 2020-2023  润新知