C语言第五章之复合类型(struct, union, enum,typedef等)

server/2024/12/21 19:06:55/

复合类型

概述

        有时我们需要将不同类型的数据组合成一个有机的整体,如:一个学生有学号/姓名/性别/年龄/地址等属性, 这时候可通过结构体实现

1. 结构体 struct

结构体(struct)可以理解为用户自定义的特殊的复合的“数据类型

变量的定义和初始化

  • 定义结构体变量的方式:
    • 先声明结构体类型再定义变量名
    • 在声明类型的同时定义变量

结构体大小

 结构体大小,由内部数据决定的
 如果是空的结构, 是由内部数据类型决定的

#include <stdio.h>
#include <string.h>// 结构体 struct
// 不同类型组合成一个有机的整体,组装成新的数组类型// 初始化
struct stu
{int id;char name[20];int age;float score;
} student;// 赋值
// 单个赋值
struct stu student = {1, "张三", 18, 100.0};// 多个赋值[]
// struct stu student[] = {
//     {1, "张三", 18, 100.0},
//     {2, "王二麻", 20, 99.0}};// struct tea
// {
//     char name[20];
//     int age;
// } teacher = {"李四", 20};int main()
{printf("id = %d", student.id);printf("name = %s", student.name);printf("age = %d", student.age);printf("score = %f", student.score);// 修改整型student.id = 2;printf("id = %d", student.id);// 修改字符strcpy(student.name, "李四");printf("name = %s", student.name);// 结构体大小,由内部数据决定的// 如果是空的结构, 是由内部数据类型决定的printf("sizeof(student) = %d", sizeof(student));return 0;
}

结构体作为参数

  • 传值是指将参数的值拷贝一份传递给函数,函数内部对该参数的修改不会影响到原来的变量

  • 传址是指将参数的地址传递给函数,函数内部可以通过该地址来访问原变量,并对其进行修改。

#include <stdio.h>
#include <string.h>struct stu
{char name[20];int age;
};void show_stucct(struct stu student)
{printf("姓名:%s\n", student.name);printf("年龄:%d\n", student.age);strcpy(student.name, "王二麻子");printf("修改后年龄:%s\n", student.name);
};// 函数参数传递结构体指针
// 指针类型需要使用->操作符void show_stucct_pointer(struct stu *student)
{strcpy(student->name, "王二麻子666");printf("姓名:%s\n", student->name);printf("年龄:%d\n", student->age);
};int main()
{struct stu s = {"张三", 18};show_stucct(s);show_stucct_pointer(&s);printf("-----------------------\n");// 指针函数传递时,会在外面修改printf("姓名:%s\n", s.name);printf("年龄:%d\n", s.age);return 0;
}

2. 共用体(联合体) union

共用体union是一个能够在同一个存储空间存储不同类型的数据的类型

共用体所占的内存长度等于其最长成员的长度

但是, 具有瞬时有效性, 每一瞬时只有一种起作用, 换句话说, 就是用谁谁有效

当存入一个新的成员后, 原有的成员值会被覆盖

共用体变量的地址和它的各成员地址都是同一地址

#include <stdio.h>//  共用体
union UN
{char ch;short sh;int i;
};int main()
{union UN un;// 查看共用体长度printf("%d\n", sizeof(un)); // 4// 都一样, 成员和共用体地址一致printf("ch = %p\n sh = %p\n i = %p\n", &un.ch, &un.sh, &un.i);printf("un = %p\n", &un);//  赋值时,影响其他数据un.i = 0x12345678;// int 4字节 char 1字节 short 2字节printf("== %0x\n  ---%0x\n", un.ch, un.sh); // 78 ---5678return 0;
}

3. 共用体和结构体区别

存储方式

  • 结构体: 每个成员都占据独立的内存空间, 成员之间按照定义的顺序依次存储
  • 共用体: 所有成员共享一块内存空间, 不同成员可以存储在同一地址上

内存占用

  • 结构体: 内存占用是成员变量内存占用的, 每个成员变量都有自己的内存地址
  • 共用体: 内存占用是成员中最大成员所占的空间大小, 不同成员变量共享同一块内存地址

4. 大端模式和小端模式

        所谓的大端模式,是指数据的低位(就是权值较小的后面那几位)保存在内存的高地址中,而数据的高位,保存在内存的低地址中,这样的存储模式有点儿类似于把数据当作字符串顺序处理:地址由小向大增加,而数据从高位往低位放;
        所谓的小端模式,是指数据的低位保存在内存的低地址中,而数 据的高位保存在内存的高地址中,这种存储模式将地址的高低和数据位权有效地结合起来,高地址部分权值高,低地址部分权值低,和我们的逻辑方法一致。

1)大端模式:

低地址 -----------------> 高地址

0x12  |  0x34  |  0x56  |  0x78

2)小端模式:

低地址 ------------------> 高地址

0x78  |  0x56  |  0x34  |  0x12

5. 枚举 enum

  • 将变量的值一一列举出来,变量的值只限于列举出来的值的范围内

  • 语法格式:

    enum  枚举名 { 枚举值表 };
    • 在枚举值表中应列出所有可用值,也称为枚举元素

      • 枚举值是常量,不能在程序中用赋值语句再对它赋值

      • 枚举元素本身由系统定义了一个表示序号的数值从0开始顺序定义为0,1,2 …

#include <stdio.h>// 枚举是值得罗列, 所有的值都是在前面基础上累加的
enum Week
{mon = 9,tue,wed,thu,fri,sat,sun
};enum bool
{// 默认是0false,true
};int main()
{enum Week day;// mon 默认是0, 后面累加. 给值就是值,后面累加printf("%d\n", mon); // 0printf("%d\n", tue); // 1if (false){printf("flag为假\n");}return 0;
}

6. typedef(重命名)

  • typedef为C语言的关键字,作用是为一种数据类型(基本类型或自定义数据类型)定义一个新名字,不能创建新类型。

#include <stdio.h>#define MAX_LENGTH 100// 把int重命名为INT
// typedef不是创造新的类型, 给类型重新命名
typedef int INT;typedef char int_8;int main()
{INT a = 10;return 0;
}

http://www.ppmy.cn/server/6545.html

相关文章

Postman之全局变量与环境变量配置

实际开发中可能需要不停切换环境&#xff0c;接口中来回输入环境地址比较麻烦&#xff0c;故而通过定义变量来节约频繁更换测试地址所耗费的时间。Postman 允许定义自己的全局变量&#xff08;Globals&#xff09;与环境变量&#xff08;Environment&#xff09;&#xff0c;最…

mysql8加密规则修改导致navicat无法连接解决方案

mysql在升级了版本后从8开始修改了加密规则&#xff0c;导致连接出现错误&#xff1a; Authentication plugin ‘caching_sha2_password‘ cannot be loaded解决方案就是更新密码以及加密方式 1 进入mysql mysql -u root -p2 修改加密规则以及密码 ALTER USER rootlocalhost…

P1278 单词游戏 简单搜索+玄学优化

单词游戏 传送门 题目描述 Io 和 Ao 在玩一个单词游戏。 他们轮流说出一个仅包含元音字母的单词&#xff0c;并且后一个单词的第一个字母必须与前一个单词的最后一个字母一致。 游戏可以从任何一个单词开始。 任何单词禁止说两遍&#xff0c;游戏中只能使用给定词典中含有…

修改Ubuntu的镜像源为中科大镜像源

修改Ubuntu的镜像源为中科大镜像源 1、首先使用以下命令备份现有的镜像源&#xff1a; cd /etc/apt sudo cp sources.list sources.list.bak 2、使用以下命令打开镜像源文件&#xff1a; sudo vim /etc/apt/sources.list 3、在vim插入模式下使用以下内容替换掉原镜像…

zabbix 自动发现与自动注册 部署 zabbix 代理服务器

zabbix 自动发现&#xff08;对于 agent2 是被动模式&#xff09; zabbix server 主动的去发现所有的客户端&#xff0c;然后将客户端的信息登记在服务端上。 缺点是如果定义的网段中的主机数量多&#xff0c;zabbix server 登记耗时较久&#xff0c;且压力会较大。1.确保客户端…

idea的maven打包只有几kb

在pom.xml文件中添加以下&#xff1a; <plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><version>2.3.4.RELEASE</version><configuration><!-- 指定该Main Class…

【Godot4.2】太极八卦图绘制

概述 作为中国传统文化符号之一&#xff0c;太极八卦图&#xff0c;无论是哲学还是玄学&#xff0c;都不可能避开。 之前在ShapePoints函数库实现了太极的点求取函数。当时采用的时圆弧拼接的方式&#xff0c;但是存在某些尺寸下多边形无法三角化的问题。 于是就有了今天的内…

死磕GMSSL通信-java/Netty系列(三)

死磕GMSSL通信-java/Netty系列&#xff08;三&#xff09; 接着上次的博客继续完善&#xff0c;上次其实只是客户端的改造&#xff0c;这次把服务端的也补上&#xff0c;netty集成GMSSL实现GMServer 1、netty_tcnative c代码改造&#xff0c;这个是客户端和服务端都需要都该的…