C语言——结构体

1 结构体初识篇

C语言的结构体其实就相当于C++里的类

c 复制代码
#include <stdio.h>
#include <string.h>

1.创建结构体
结构体类型-->描述结构化数据
	struct 标识符
 {
	  特征--->基本数据类型描述
 };

struct  MM 
{
	char name[20];
	int age;
	int num;
	char addr[20];
};
1.1 C语言不允许空的结构体存在
	//struct empty 
	//{
	//};

-----------------------------------------------------------------------------------------
    
2.怎么访问数据
2.1 结构体中数据必须要通过结构体变量访问
2.2 怎么创建结构体变量  类型+变量名;
2.3 访问方式
	 结构体变量  变量.成员
	 结构体指针  指针->成员
int main() 
{	
	//创建结构体变量
	struct MM  girl;
    
	//数组不能不能直接赋值需要strcpy
	//girl.name = "sdfg";
	strcpy_s(girl.name, 20, "小美");
	girl.age = 38;
	//指针用->  一般不这样写
	(&girl)->num = 1001;
	strcpy_s(girl.addr, 20, "我家");
	printf("%s\t%d\t%d\t%s\n", girl.name, girl.age, girl.num, girl.addr);
    
    
	//类型* 变量名;
	struct MM* pMM = NULL;
	//有问题 NULL里面没有age
	//pMM->age = 123;(错误)
	pMM = &girl;
	printf("%s\t%d\t%d\t%s\n", (*pMM).name, (*pMM).age, (*pMM).num, (*pMM).addr);
	//->  指针指向运算符   这种好看
	printf("%s\t%d\t%d\t%s\n", pMM->name, pMM->age, pMM->num, pMM->addr);

	return 0;
}

2 结构体的创建与初始化

c 复制代码
#include <stdio.h>
struct MM 
{
	char name[20];
	int age;
	double score;
};
-----------------------------------------------------------------------------------------
2.结果体变量创建
struct MM g_mm = { "全局",18,1.2f };//先创建再初始化
struct Data 
{
	char name[20];
	int age;
	double score;
}value = {"全局",18,1.0f},arr[3],a,b;
//value是变量名
//value ,a,b 都是一个结构体变量
//arr[3] 结构体数组

-----------------------------------------------------------------------------------------

3.typedef 与结构体创建(可以简化代码,目前觉得鸡肋,代码长了就有用了)
typedef struct Test 
{
	char name[20];
	int age;
	int score;
}Test,*PTest,ARRAY[3];
//Test,*PTest,ARRAY[3] 都是类型别名
//typedef struct Test Test,
//typedef struct Test *PTest,
//typedef struct Test ARRAY[3];
void  test_typedef_struct() 
{
	struct Test t1;
	Test t2;			//struct Test t2
	struct Test* p1 = NULL;
	PTest p2 = NULL;	// struct Test *p2

	struct Test array1[3];
	ARRAY array2;		// struct Test array2[3]
}
-----------------------------------------------------------------------------------------
    
4 特殊结构体定义
struct  //没有名字的结构体这个结构体只有一个变量
{
	int num;
	int key;
}SingleTon;

typedef struct //有typedef,就有了别名,可以随意创建变量
{
	int num;
	int key;
}Type;
void test() 
{
	Type a = { 1,2 };
	Type b = { 2,3 };//可以无限定义变量
	SingleTon.num = 23;
	SingleTon.key = 123;//只有这两个
}

-----------------------------------------------------------------------------------------

int main() 
{
	//1.可以创建变量的时候用大括号方式初始化(局部的)
	struct MM mm1 = { "小帅",18,1.234 };
	struct MM mm2 = { "小美"};	//age和score默认为0
	struct MM mm3 = { .age = 12,.name = "小花",.score = 1.2f };
	printf("%d\t%.2lf\n", mm2.age, mm2.score);
	printf("%s\t%d\t%.1lf\n", mm3.name, mm3.age, mm3.score);
	
    test_typedef_struct() 
        
    //测试3    
    struct black_red_node* p = (struct black_red_node*)malloc(sizeof(struct black_red_node));
	RBNode* p1 = (RBNode*)malloc(sizeof(RBNode));    
	return 0;
}

3 结构体数组

c 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
struct MM 
{
	char name[20];
	int age;
	char addr[20];
};
//1 输入和打印
void test() 
{
	struct MM arr[3];
	printf("input mm(3):");
	for (int i = 0; i < 3; i++)
	{
		//scanf("%s%d%s", arr[i].name,&arr[i].age, arr[i].addr);
		scanf_s("%s%d%s", arr[i].name, 20, &arr[i].age, arr[i].addr, 20);//scanf_s要加尺																		寸,别的编译器不用
	}
	printf("姓名\t年龄\t编号\n");
	for (int i = 0; i < 3; i++)
	{
		printf("%s\t%d\t%s\n", arr[i].name, arr[i].age, arr[i].addr);
	}
}
-----------------------------------------------------------------------------------------
    
//2 结构体数组的冒泡排序(传函数指针的方式)    
void bubble_sort(struct MM* arr, int arrayNum,bool(*compare)(struct MM,struct MM)) 
{
	for (int i = 0; i < arrayNum; i++) 
	{
		for (int j = 0; j < arrayNum - i - 1; j++) 
		{
			//比较规则,剥洋葱
			if (compare(arr[j],arr[j+1]))
			{
				//memcpy
				struct MM temp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = temp;
			}
		}
	}
}
void print_mm(struct MM arr[], int arrayNum) 
{
	printf("姓名\t年龄\t编号\n");
	for (int i = 0; i < arrayNum; i++)
	{
		printf("%s\t%d\t%s\n", arr[i].name, arr[i].age, arr[i].addr);
	}
}
//可以自己写按什么方式去比较(用函数指针升级一下)
bool compare_by_age(struct MM one, struct MM two) 
{
	return one.age > two.age;
}

bool compare_by_name(struct MM one, struct MM two)
{
	return strcmp(one.name,two.name)>0;
}
bool compare_by_addr(struct MM one, struct MM two)
{
	return strcmp(one.addr, two.addr)>0;
}

-----------------------------------------------------------------------------------------

int main() 
{
	struct MM data[5] = 
	{  "4小芳",18,"6地球",
		"2小花",48,"776号" ,
		"1小美",28,"8海南" ,
		"4小李",38,"9天津" ,
		"6小小",58,"0西藏"
	};
	bubble_sort(data, 5,compare_by_age);
	print_mm(data, 5);
	bubble_sort(data, 5, compare_by_name);
	print_mm(data, 5);
	bubble_sort(data, 5, compare_by_addr);
	print_mm(data, 5);
	return 0;
}

4 位段

以后可能会看见,但自己很少用(做特别精小的软硬件)

c 复制代码
#include <stdio.h>
#include <stdlib.h>
struct Flag 
{
	//:后面的数字代表的是变量占用内存是多少个二进制位
	unsigned int a : 3;	//3个二进制位   _ _ _  最小000  最大111
	unsigned int b : 2;	//2个二进制位   _ _    最小00  最大11
	unsigned int c : 3;	//3个二进制位
};
int main() 
{
	//溢出:超过存储范围
	struct Flag flag;
	flag.a = 5;
	flag.b = 1;
	flag.c = 8;  //_ _ _ _  1000
	printf("溢出:%u\n", flag.c);//无符号打印%u,打印后三位就是0
	printf("a=%u,b=%u\n", flag.a, flag.b);//打印5,1
	flag.c = 9;	//1001
	printf("溢出:%u\n", flag.c);//打印1
	return 0;
}

5 枚举类型和共用体

c 复制代码
#include <stdio.h>
#include <string.h>

1.创建枚举
//enum 标识符{符号...}符号常量
enum Color{Red,Blue,Yellow,Green};
//默认值  Red=0 Blue=1 Yellow=2 Green=3

-----------------------------------------------------------------------------------------

2干啥用,咋用 
//程序中需要大量具有相同含义数字------>推箱子
2.1枚举菜单项
enum Menu {Insert,Delete,Modify,Sort,Search};
void keyDown()
{
	int key;
	scanf_s("%d", &key);
	switch (key) 
	{
	case Insert:
		break;
	case Delete:
		break;
	case Modify:
		break;
	case Sort:
		break;
	case Search:
		break;
	}
}
2.2初始化规则------>没有初始化的是前面的加1
enum Dir {Left=75,Right,Up=80,Down,Mid};
//Right: 75+1
//Down: 80+1
//Mid:Down+1=80+2

-----------------------------------------------------------------------------------------

3.C语言枚举类型当函数参数,也是可以传入整形变量
void print_value(enum Dir a) 
{
	printf("%d\n", a);
}

-----------------------------------------------------------------------------------------

共用体 union
union  Value
{
	char name[20];
	int age;
};

void test_union()
{
	//共同体 -->也叫联合体
	//所有变量共用同一块内存,一段内存给两个变量用
	//union Value value = { "A",65};  //不能同时初始化两个变量
	union Value value;
	strcpy_s(value.name, 20, "A");
	puts(value.name);
	printf("%d\n", value.age);	//65
	//value.age = 65;
	//printf("%d\n", value.age);
	//puts(value.name);
}

-----------------------------------------------------------------------------------------

int main() 
{	
    //1
	printf("Red:%d\n", Red);//1
	printf("Blue:%d\n", Blue);//2
    //2
	printf("Mid:%d\n", Mid);//82
	//3
	print_value(999);
	print_value(Left);
    //共用体
    test_union();
	return 0;
}

6 结构体嵌套

c 复制代码
#include <stdio.h>
#include <stdlib.h>
//推荐嵌套 
struct Score 
{
	int math;
	int english;
	int py;
};
struct Info 
{
	char name[20];
	int age;
	char addr[20];
	char tel[14];
};
struct Student 
{
	struct Info info;
	struct Score score;
};

-----------------------------------------------------------------------------------------
    
//直接包含(个人感觉有一点别扭)
struct A 
{
	int a;
	struct B 
	{
		int age;
		int num;
	}b;//一般这里跟一个变量
};

-----------------------------------------------------------------------------------------

int main() 
{
	struct Student stu = { {"小芳",18,"火星","18934873456"},{88,89,99}};
	printf("%s\t%d\t%s\t%s\t%d\t%d\t%d\n", 
		stu.info.name,
		stu.info.age,
		stu.info.addr,
		stu.info.tel,
		stu.score.math,
		stu.score.english,
		stu.score.py);

	struct A object = { 1,{23,45} };
	printf("%d\t%d\t%d\n", object.a, object.b.age, object.b.num);
	return 0;
}

7 结构体中的指针

时刻考虑内存问题

c 复制代码
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
struct MM 
{
	char* name;
	int age;
};


//返回一个堆区的结构体变量
struct MM* create_mm(const char* name, int age) 
{
	struct MM* temp = (struct MM*)malloc(sizeof(struct MM));
	assert(temp);
	//temp->name = name;
	int length = strlen(name) + 1;
	temp->name = (char*)malloc(length);
	strcpy_s(temp->name, length, name);
	temp->age = age;
	return temp;
}

-----------------------------------------------------------------------------------------

int main() 
{
	struct MM one = { "ILoveyou",18 };
	struct MM two = { "小花",28 };
	struct MM temp = one;
	one = two;
	two = temp;
	printf("%s\t%d\n", one.name, one.age);
	printf("%s\t%d\n", two.name, two.age);
	//这个操作就是错误的
	// name是指针,没有内存
	//strcpy_s(one.name, 20, "小可爱");
	one.name = (char*)malloc(20);
	assert(one.name);
	strcpy_s(one.name, 20, "小可爱");
	printf("%s\t%d\n", one.name, one.age);
	struct MM* p = create_mm("小宝贝", 18);
	printf("%s\t%d\n", p->name, p->age);
	return 0;

8 结构体内存问题

(有学业需求的)封装------>减少内存,传输数据就少点

c 复制代码
#include <stdio.h>
#include <string.h>
#include <malloc.h>
#include <assert.h>
1
//具体占用内存多少其实不是那么重要,
//怎么写才省内存才是重要的。
    
-----------------------------------------------------------------------------------------
    
2 内存对齐
(按成员最长字节对齐)
//char 可以拆分
//char可以和int以及float填补
struct MM 
{	
	char name[20];  //8+8+ 多4可以和下面的补一起
	int age;        //4+上面的多4
	double num;		//8
    //8+8+4+4+8=32
};

struct Data 
{
	char name[20];  //8+8 多4不能和下面补,要多补4
	double num;     //8
	int age;        //4+补4
    //8+8+4+4+8+4+4=40
};

一样的东西,写法顺序不一样,内存多占8位,数据特别大的时候流量就用的多了
-----------------------------------------------------------------------------------------

struct Value 
{
	char name[3];	//3 补1
	int age;        //4
	char id[2];     //2 补2
};
struct Test 
{	//64位中,指针占8个字节
	char name[9];   //8+1+补7
	char* p;		//8
	int age;        //4 +补4
    //8+1+7+8+4+4=20
};

-----------------------------------------------------------------------------------------
int main() 
{
    //1
	//自己写代码一个sizeof就行了,自己不用算内存是多少
	printf("%zd\n", sizeof(struct MM));
	struct MM* p = (struct MM*)malloc(sizeof(struct MM));
	assert(p);
	
    //2
	printf("MM:%zd\n", sizeof(struct MM));
	printf("Data:%zd\n", sizeof(struct Data));
	printf("Value:%zd\n", sizeof(struct Value));
	printf("Test:%zd\n", sizeof(struct Test));
	return 0;
}



#pragma pack(8)写在头文件中------>代表着指定每个成员按照8字节对齐
相关推荐
Yui_NIE2 小时前
解决core-js报错:These dependencies were not found: core-js/modules/es.array.push.js
开发语言·前端·javascript
C++oj4 小时前
普及组集训图论--判断负环
数据结构·算法·图论·spfa·判断负环
梅茜Mercy4 小时前
数据结构:通讯录(顺序表的应用)的实现详解
c语言·数据结构
Harryline-lx4 小时前
代码随想录算法训练营Day31 | 56. 合并区间、738.单调递增的数字、968.监控二叉树、贪心算法总结
算法·贪心算法
Dong雨5 小时前
ShardingSphere-JDBC
java·开发语言·数据库
直裾5 小时前
Scala的隐式转换规则
开发语言·后端·scala
IT古董5 小时前
【机器学习】机器学习的基本分类-监督学习-Lasso 回归(Least Absolute Shrinkage and Selection Operator)
学习·算法·机器学习·分类·回归
写bug的小屁孩5 小时前
用户信息界面删除好友功能
运维·服务器·c语言·c++·qt·websocket·http
Steven_Mmm5 小时前
使用Allure作为测试报告生成器(Java+Selenium)
java·开发语言·selenium
深圳函数5 小时前
常见的面试算法题
算法·面试·职场和发展