复合类型
概述
有时我们需要将不同类型的数据组合成一个有机的整体,如:一个学生有学号/姓名/性别/年龄/地址等属性, 这时候可通过结构体实现
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 ---5678
return 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
{
// 默认是0
false,
true
};
int main()
{
enum Week day;
// mon 默认是0, 后面累加. 给值就是值,后面累加
printf("%d\n", mon); // 0
printf("%d\n", tue); // 1
if (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;
}
本文介绍了C语言中如何通过结构体组合不同类型数据,以及共用体、大端模式、小端模式和枚举的使用。还讨论了typedef用于数据类型重命名的功能。
606

被折叠的 条评论
为什么被折叠?



