C语言 自定义数据类型(结构体 typedef 共用体 位段 枚举)

本文介绍了如何定义和使用结构体,包括变量初始化、成员访问、结构体指针,以及结构体数组。还讲解了typedef的使用,简化类型定义,并涉及共用体、位段和枚举的基本概念。适合初学者理解数据类型扩展在C语言中的应用。
摘要由CSDN通过智能技术生成

1、结构体的定义及初始化

        通过数据类型来定义一个一个的变量,当需要很多相同类型的变量时有数组。 基本数据类型在使用时很方便,但是利用它们来描述现实世界就显得捉襟见肘。 例如需要保存一个班学生的信息”姓名,年龄,分数”,按照前面的学习需要单独 定义三个数组,一个保存姓名,一个保存年龄,一个保存分数。这样定义对于后面 的维护,修改,删除会带来麻烦。好比你用三个记事本一个记录学生姓名,一个记 录年龄,一个记录分数,如果删除姓名记事本中的第十个学生,而在年龄,分数记 事本中却删除了第十一个,这是很容易发生的。实际中并不会这么做,我们会利用 一个 Excel 表来记录学生的信息,一行就是一个学生的所有信息,修改,添加,删 除都非常清晰。而这就是今天学习的内容-自定义数据类型。

        自定义数据类型:根据自己的需要定义新的数据类型。

        自定义数据类型包括结构体,位段,共用体和枚举。当然最重要的就是一号选 手-结构体。

        例如:定义一个学生结构体,包含姓名和年龄

struct Student //定义学生结构体
{
    char name[20];//姓名
    int age; //年龄
}; //类型定义完成

        这个类型定义好了之后就和基本类型一样使用,可以用来定义单个变量,数 组,指针或者作为另一个结构体的成员。 

         结构体变量定义好之后该如何访问它的成员呢?如何输出 stu3 中的信息呢? 结构体变量通过”.”号访问其成员。

        输出 stu3 信息的代码如下:

        printf("%s,%d\n",stu3.name,stu3.age);//通过.号访问成员

struct Student //定义学生结构体
{
    char name[20];//姓名
    int age; //年龄
}; //类型定义完成

int main()
{
    struct Student stu1;
    struct Student stu2 = {"caocao"};
    struct Student stu3 = {"刘备",25};
    printf("%s,%d\n",stu3.name,stu3.age);//通过.号访问成员

    //修改成员的数据
    strcpy(stu1.name,"孙权"); //字符串复制需要用 strcpy
    stu1.age = 18; //通过.号访问成员
    printf("%s,%d\n",stu1.name,stu1.age);//通过.号访问成员

    strcpy(stu2.name,"曹操"); //通过.号访问成员
    stu2.age = 24; //通过.号访问成员
    printf("%s,%d\n",stu2.name,stu2.age);
    
    return 0;
}

 


         2、结构体指针定义及使用

         结构体指针定义

         结构体不仅能定义普通的变量,也可以定义指针,例如:

struct Student //定义学生结构体
{
   char name[20];//姓名
   int age; //年龄
};

int main()
{
    int a = 10;
    int *p = &a;

    struct Student stu = {"曹操",23};
    struct Student *ps = &stu;//类似 p
    struct Student *ps2; //没有初始化,野指针

    return 0;
}

        结构体指针变量和整型指针变量类似,用于保存同类型变量的地址 

        结构体指针访问其成员 结构体指针 ps 如何访问结构体的成员呢?一个笨办法就是(*ps).age 这种形 式。注意一定要加”()”,因为”*”的优先级低于”.”,这个办法不仅容易出错, 写起来也繁琐,C 语言有一种更简洁的表达形式。

        结构体指针通过”->”访问其成员。   

        例如下面代码。

int main()
{
    int a = 10;
    int *p = &a;

    struct Student stu = {"曹操",23};
    struct Student *ps = &stu; //类似 p
    struct Student *ps2; 
    printf("%s,%d\n",(*ps).name,(*ps).age);//这个方法繁琐,易错
    printf("%s,%d\n",ps->name,ps->age); //结构体指针访问其成员
    ps2 = &stu;
    ps2->age = 30; //通过 ps2 修改 stu 的年龄
    printf("%s,%d\n",ps2->name,ps2->age);

    return 0;
}

        总结:结构体变量通过”.”访问其成员,结构体指针通过”->”访问其成员。


        3、结构体数组定义及使用 结构体数组定义 结构体定义完成后和内置类型一样使用,能定义变量,指针当然也可以定义数组。

struct Student
{
    char name[20];
    int age;
};

int main()
{
    //内置类型,定义变量,指针和数组
    int a = 10;
    int *p = &a;
    int arr[10] = {1,2,3};

    //结构体类型,定义变量,指针和数组
    struct Student stu = {"曹操",23};
    struct Student *pstu = &stu;
    struct Student brr[3];
    struct Student crr[3] = {{"曹操",23},{"刘备",25},{"孙权",18}};
    struct Student drr[3] = {"曹操",23,"刘备",25,"孙权",18};
    struct Student err[] = {"曹操",23,"刘备",25,"孙权",18};
    return 0;
}


5、typedef 的使用

        在 C 语言中使用结构体时必须加上 struct 这个关键字,那有没有办法省略这 个呢?要想达到这个目的就需要用到关键字 typedef,顾名思义”类型定义”。

        typedef 数据类型 新的别名;

        它是用来操作数据类型。其主要作用有两个:

        1.给一个较长较复杂的类型取一个简单的别名。

        2.给类型取一个和问题相关的别名。

        如何在使用结构体时省略 struct 这个关键字呢?可以 按照如下方法定义结构体。例如:

//第一个方式
struct A
{
    int a;
    char b;
};
typedef struct A A;//给 struct A 起个别名叫 A

//第二种方式
typedef struct B
{
    char a;
    int b;
}B; //给 struct B 起个别名叫 B

int main()
{
    A aa = {10,'x'}; //直接使用 A
    B bb = {'y',20}; //直接使用 B

    return 0;
}

        6、共用体,位段和枚举

        共用体

        共用体也称为联合体,使用关键字 union,它的所有成员共用同一段内存。例如:

typedef struct A
{
    int a;
    int b;
}A;

typedef union B
{
    int a;
    int b;
}B;

int main()
{
    A aa = {10,20};
    //B bb = {10,20};//错误,B 中所有成员共用同一段内存,不能同时赋值
    B bb;
    bb.a = 10;
    bb.b = 20;
    printf("%d,%d\n",aa.a,aa.b);
    printf("%d,%d\n",bb.a,bb.b);

    return 0;
}

         注意在上图中 bb.a = 10,但是在输出结果时却是 20,为什么会这样呢?见下 面的内存图:  

      

         原因还是因为共用体所有成员共用同一段内存,如上图在联合体 union B 中 a 和 b 的内存相同。第 19 行代码 bb.b = 20 时会将前面 bb.a 的值也修改成 20。

        总而言之使用联合体的准则是:联合体定义的一个变量一定只使用其中的一 个成员。


        位段

        位段和结构体非常的类似,它成员表示一个或者多个位。由于不同平台,它的 定义有差异(C 标准没有详细定义),所以它不可移植,使用起来不如位运算方便, 在这不做过多介绍,大家只需要认识并知道它的大小即可。

struct A
{
    int a;
    int b;
};

struct B //定义位段
{
    int a:10;//表示 a 占用 10 个位
    int b:20;//表示 b 占用 20 个位
};

int main()
{
    printf("sizeof(struct A)=%d\n",sizeof(struct A));
    printf("sizeof(struct B)=%d\n",sizeof(struct B));
    return 0;
}

 

        位段的大小一定是 sizeof(int)的倍数,上例中位段 B 为 10+20 共 30 位,最 小为 4 字节(32 位)。


         枚举

        枚举:使用关键字 enum,把可能的值全部列举出来,变量的取值只能在列举 的值范围内。 例如枚举星期类型:

enum Weekday{sun,mon,tue,wed,thu,fri,sat};

int main()
{
    enum Weekday day1; //定义变量,未初始化
    enum Weekday day2 = sun; //初始化为星期天
    enum Weekday day3 = mon; //初始化为星期一
    return 0;
}

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

安冉冄先森

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值