7.C语言结构体篇

结构体的定义

  • 自定义的数据类型
  • 有一批数据组合而成的结构类型数据
  • 其中的每一个数据都是结构体的“成员”
  • 其实就相当于Java中的类(当然没有Java中的类那么好用就是了)

格式

struct 结构体名

{

​ 成员1(理解成Java类中的属性就好);

​ 成员2;

​ 。。。

}

如何使用

在函数中:struct 结构体名 自定义变量名;

#include<stdio.h>
#include<string.h>

struct Student
{
	char name[100];
	int age;

};

int main()
{
	//第一种初始化方法
	struct Student st1;
	strcpy(st1.name, "张三");
	st1.age = 20;
	printf("学生1的名字是:%s\n学生的年龄是:%d\n", st1.name, st1.age);
	//第二种初始化方法
	struct Student st2 = { "李四", 21 };
	struct Student st3 = { "王五", 22 };
	struct Student st4 = { "赵六", 23 };
	printf("\n学生2的名字是:%s\n学生的年龄是:%d\n", st2.name, st2.age);
	printf("\n学生3的名字是:%s\n学生的年龄是:%d\n", st3.name, st3.age);
	printf("\n学生4的名字是:%s\n学生的年龄是:%d\n", st4.name, st4.age);
	return 0;
}

别名

格式:

​ typedef struct (可选)结构体名

​ {

​ 成员. . .

​ } 别名;

好处:

  • 使用时可以直接使用别名,不再需要带上前缀“struct”

结构体作为函数参数

  • 函数中可以传递结构体
    1. 传递结构体的数据值
    2. 传递结构体的地址值
#include<stdio.h>
#include<string.h>

typedef struct Student
{
	char name[100];
	int age;
} S;

void reS(S* p);

int main()
{
	S stu1;
	strcpy(stu1.name, "aaa");
	stu1.age = 0;
	printf("修改前的学生姓名是:%s 年龄是:%d\n", stu1.name, stu1.age);
	reS(&stu1);
	printf("\n修改后的学生姓名是:%s 年龄是:%d\n", stu1.name, stu1.age);
	return 0;
}
//定义一个函数,修改学生的数据
void reS(S* p)
{
	printf("\n请输入要修改的名称:");
	scanf("%s", (*p).name);
	printf("请输入要修改的年龄:");
	scanf("%d", &((*p).age));

}

结构体嵌套

  • 结构体中成员的类型是其他的结构体
#include<stdio.h>
#include<string.h>

typedef struct Massage
{
	char phone[12];
	char meil[100];

}M;

typedef struct Student
{
	char name[100];
	int age;
	char sex;
	double height;
	M massage;

}S;

int main()
{
	//第一种初始化赋值方式
	S s1;
	strcpy(s1.name, "张三");
	s1.age = 23;
	s1.sex = 'F';
	s1.height = 1.73;
	strcpy(s1.massage.phone, "12345678901");
	strcpy(s1.massage.meil, "1234567890@qq.com");
	printf("姓名为:%s\n年龄为:%d\n性别为:%c\n身高为:%.2lf\n手机号为:%s\n联系邮箱为:%s", s1.name, s1.age, s1.sex, s1.height, s1.massage.phone, s1.massage.meil);
	printf("\n------------------------------\n");
	//第二种初始化赋值方式
	S s2 = { "李四", 25, 'F', 1.83, {"12345678901", "1234567890@qq.com"} };
	printf("姓名为:%s\n年龄为:%d\n性别为:%c\n身高为:%.2lf\n手机号为:%s\n联系邮箱为:%s", s2.name, s2.age, s2.sex, s2.height, s2.massage.phone, s2.massage.meil);
	return 0;
}

结构体内存对齐机制

  • 确定变量位置:只能放在自己类型整数倍的内存地址上

  • 最后一个补位:结构体的总大小,是最大类型的整数倍

  • struct num
    {
        double a; 	// 8
        char b;		// 1 + 3
        int c;		// 4
        char d;		// 1 + 7
    }
    
地址 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17+7
变量 a a a a a a a a b \0 \0 \0 c c c c d \0+7
  • \0:C自动填补的空字节 (我自己定义的,好记好写)

  • \0 + 7:总共7个空字节

  • 习俗:

    • 在定义数据类型时,按照数据类型占用字节从小到大的顺序进行定义(尽最大可能规避掉C自动填补的空洞字节)

共同体(共用体/联合体)

  • 作用,可以同时接收一个含义的不同数据类型
  • 格式:(也可以像结构体那样起别名“typedef”)

​ union 共同体名

​ {

​ 数据类型1;

​ 数据类型2;

​ . . .

​ }

  • 特点:
    • 所有的变量都使用同一个内存空间
    • 所占内存大小 = 最大单个成员的长度(也受内存对齐影响)
      • 总大小一定是最大单个成员长度的整数倍(内存对齐)
    • 每次只能给一个变量进行赋值,第二次赋值时会覆盖上一次赋值的数据(原因:第一个特点)
#include<stdio.h>
#include<string.h>

//定义一个共同体
typedef union Money
{
	int moneyi;
	double moneyd;
	char moneystr[100];
} M;

int main()
{
	M m;
	// 查看内存地址
	printf("%p\n", &m.moneyi);		// 000000C40C78F790
	printf("%p\n", &m.moneyd);		// 000000C40C78F790
	printf("%p\n", &m.moneystr);	// 000000C40C78F790
	// 查看所占内存大小
	printf("\n%zu\n", sizeof(m.moneyi));	// 4
	printf("%zu\n", sizeof(m.moneyd));		// 8
	printf("%zu\n", sizeof(m.moneystr));	// 100
	printf("%zu\n\n", sizeof(m));			// 104(内存对齐)
	// 查看后数据是否会覆盖前数据
	m.moneyi = 100;
	printf("%d\n", m.moneyi);		// 100
	m.moneyd = 99.5;
	printf("%.2lf\n", m.moneyd);	// 99.50
	strcpy(m.moneystr, "100万");
	printf("%s\n", m.moneystr);		// 100万
	return 0;
}

结构体和共同体的区别

  • 结构体:
    • 一种事物中包含多个属性(和Java中类的概念类似)
    • 存储方式:各存各的
    • 内存占用:各个变量的总和(受内存对齐影响)
  • 共用体:
    • 一个属性有多种类型
    • 存储方式:存一起,多次存会覆盖
    • 内存占用:最大类型(受内存对齐影响)
posted @ 2026-03-14 15:45  Shadow001  阅读(1)  评论(0)    收藏  举报