2020.9.28 第12节 结构体初识

2020.9.28 第12节 结构体初识

一、结构体初识

1.结构体是什么东西? 内存上的样子

1.1 是一种新的数据类型---->自定义类型

1.2 为什么有结构体

1.3 完整定义结构体的语法

struct 标识符

{

基本数据类型;

};

2. 如何定义结构体变量

int num;

struct 结构体名 变量名; //结构体变量

int *p;

struct 结构体名* 指针名; //结构体指针

int array[4]; //结构体数组

struct 结构体名 数组名[数组长度]

3.如何访问结构体中成员

3.1 变量去访问: 变量.成员

3.2 指针访问: 结构体指针->成员

(*结构体指针).成员 //变量.成员
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
//<1>最常见的定义方式
struct MM			//struct MM : 类型
{
	char name[20];
	int age;
	int num;
};
//全局的结构体变量
struct MM g_MM = { "g_MM",19,1003 };
//<2>.没有结构体名的结构体
struct    //没有类型
{
	char name[20];
	int age;
	int num;
}role = {"g_role",29,1004};			//role : 唯一 一个结构体变量
//role 等效上面
//类型  变量名  
//struct MM object;   //object: 结构体变量  struct MM : 自定义类型
struct boy 
{
	char name[20];
	int age;
	int num;
}bRole;
//bRole : struct boy bRole;
struct boy bRole2;
struct boy bRole3;

int main() 
{
	//1.结构体变量
	struct MM myMM;
	printf("请输入姓名,年龄,编号:");
	scanf("%s%d%d", myMM.name, &myMM.age, &myMM.num);
	printf("%s\t%d\t%d\n", myMM.name, myMM.age, myMM.num);
	//1.1 定义变量去初始化   注意!!!
	struct MM yourMM = {"Baby",18,1002};
	//错误写法
	//struct MM object;
	//object = { "Baby",18,1002 };
	role.age = 38;
	role.num = 9999;
	//2.结构体指针
	struct MM* pMM;
	//3.结构体数组
	struct MM array[4];
	return 0;
}

二、结构体数组的基础

多个事物具有相同的属性 抽象过程

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
struct MM 
{
	char name[20];
	int age;
	int num;
};
//多次使用多种不同的数据的时候,采用结构体去封装
struct Tar 
{
	int x;
	int y;
	char target;
	int speed;
};
struct Tar array[10];

int main() 
{
	struct MM myMM[3]; //myMM[0]  myMM[1] myMM[2]
	printf("请输入三个学生的信息:\n");
	for (int i = 0; i < 3; i++) 
	{
		printf("请输入第 %d 位的信息:", i + 1);
		//myMM[0]
		//myMM[1]
		scanf("%s%d%d", myMM[i].name, &myMM[i].age, &myMM[i].num);
		//scanf("%s%d%d", (myMM+i)->name, & (myMM+i)->age, & (myMM+i)->num);
	}
	printf("姓名\t年龄\t编号\n");
	for (int i = 0; i < 3; i++) 
	{
		printf("%s\t%d\t%d\n", myMM[i].name, myMM[i].age, myMM[i].num);
	}
	char name[10][20];  //10个人的姓名
	return 0;
}

三、结构体指针

指针要充当变量使用:变量存值

1.指向变量

2.动态内存申请

经典错误 指针当作指针变量使用时
0的内存不能修改 p本身是没有内存的
//不先定义结构体变量然后 再用结构体指针指向它 
如果要一个动态申请的结构体数组,更多的是数组
#include <stdio.h>
#include <string.h>
struct MM 
{
	char name[20];
	int age;
	int num;
};
int main() 
{    //把0 强制转换为一个地址 
	struct MM* p = NULL;  //NULL:(void*)0
//经典错误
	//指针要充当变量使用: 变量存值
	//1. 指向变量   //避免对空指针做非法操作
	struct MM myMM;
	p = &myMM;  
	strcpy(p->name, "ILoveyou");
	p->age = 18;
	p->num = 1001;
	printf("%s\t%d\t%d\n", myMM.name, myMM.age, myMM.num);
	printf("%s\t%d\t%d\n", (*p).name, (*p).age, (*p).num);
	printf("%s\t%d\t%d\n", p->name, p->age, p->num);
	//2. 动态内存申请
	struct MM* pMM = (struct MM*)malloc(sizeof(struct MM));
	strcpy(pMM->name, "MM");
	pMM->age = 18;
	pMM->num = 1001;
	//不先定义结构体变量然后 再用结构体指针指向它
	//动态申请的结构体数组,结构体指针变结构体数组
	//struct MM pArray[3];
	struct MM* pArray = (struct MM*)malloc(sizeof(struct MM) * 3);
	//错误
	//int* p = NULL; //(void *)0  强制转换语法 (目标类型)变量
	//*p = 100;
	return 0;
}

四、typedef和结构体的定义

如何看别名,把中间的数据全部省略掉

#include <stdio.h>
#include <string.h>
#include <windows.h>
typedef struct student_score_info 
{
	char name[20];
	int age;
	int num;
}SSI,*LPSSI,SARRY[2];  //结构体 结构体指针 结构体数组 的别名
/*
//如何看别名,把中间的数据全部省略掉
typedef struct student_score_info  SSI; 
typedef int INT;

typedef struct student_score_info* LPSSI
typedef int * LPINT;

typedef struct student_score_info SARRY[2]
typedef int array[2];

*/

struct MM 
{
	char name[20];
	int age;
	int num;
};
typedef struct MM MMTYPE;
typedef struct MM* LPMM;
int main() 
{
	//正常写法
	struct student_score_info mm;
	SSI  t_mm;
	struct student_score_info* pMM = &mm;
	LPSSI p = &mm;  //结构体指针的别名一定要有标识前缀  LP代表指针
	//LPVOID lpvoid = NULL;  //void *   windows里面LPVOID
	struct student_score_info array[2];
	SARRY myarray;
	return 0;
}

五、结构体中指针

1.结构体中的字符数组只能用strcpy,只是首地址

2.如果是指针? 不能直接赋值

yourBoy.name = (char*)malloc(strlen(inputName) + 1);
	strcpy(yourBoy.name, inputName);
#include <stdio.h>
#include <string.h>
struct MM 
{
	char name[20];
	int age;
	int num;
};

struct Boy 
{
	char* name;   //如果是指针? 不能直接赋值
	int age;
	int num;
};

int main() 
{
	struct MM mm;
	必须采用字符串拷贝操作
	strcpy(mm.name, "MM");
	//mm.name[0] = 'A';
	//mm.name[1] = '1';
	//错误: mm.name="MM";
	struct Boy yourBoy;
	char inputName[20];  用户去输入,临时变量暂时存储 name为指针时
	printf("inputName:");
	scanf("%s", inputName);   充分利用内存,可见长度
	//--------------------------------------------------
	yourBoy.name = (char*)malloc(strlen(inputName) + 1);
	strcpy(yourBoy.name, inputName);
	//--------------------------------------------------
	yourBoy.age = 10;
	yourBoy.num = 1001;
	free(yourBoy.name);
	yourBoy.name = NULL;
	return 0;
}

六、内存对齐

C语言中不允许空的结构体

	内存问题: 不对齐 所有内存之和
		对齐的方式: 地址总线   寻址这一快
	节省内存的写法:
		字符当一个字节处理
		从小到大写
	具体去算字节数:按最长的对齐  3+1  4  8  3+5 8 4+4

#include  <stdio.h>
#include <string.h>
struct MM 
{
	char name[3];	//3
	int inum;		//4
	double num;		//8
	int age;		//4
};
int main() 
{
	占用多少内存只和内存申请有关系
	struct MM* pMM = (struct MM*)malloc(sizeof(struct MM));
	printf("%d\n", sizeof(struct MM));
	return 0;
}

七、联合体和枚举型

1.联合体—>共用体 一个东西

所有变量的共用最长的内存.

struct 关键字改为union 不能同时初始化全部的变量

每一次只能用一个 一般用在开关

2.枚举类型: 整形常量

项目一些具有代表性的常量的符号替换


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
union MM
{
	char name[30];
	int age;
	int num;
};
项目一些具有代表性的常量的符号替换
enum direction {UP=72,DOWN=80,LEFT=75,RIGHT=77};
//默认的值:0 1 2....
//enum weekdays{一,二,三,四,五,六,七};
enum weekdays{,,,,,,};
//局部的默认: 是前者的+1
enum COLOR {RED=1,BLACK,YELLOW=9,BLUE};

int main() 
{
	union MM myMM = { "10"};
	strcpy(myMM.name, "1001");
	printf("%s\n", &myMM.age);
	myMM.age = 99;
	printf("%d\n", myMM.age);
	printf("%s\n", &myMM.name);
	printf("%d\n", myMM.num);
	printf("BLACK:%d\t,BLUE=%d\n", BLACK, BLUE);
	while (1) 
	{
		char userKey = _getch();
		switch (userKey) 
		{
		case UP:
			printf("%d\t",);
			break;
		case DOWN:
			printf("%d\t",);
			break;
		case LEFT:
			printf("%d\t",);
			break;
		case RIGHT:
			printf("%d\t",);
			break;
		}
	}
	return 0;
}

八、位段结构体

对所有变量的内存使用精准到二进制位 二极管

#include <stdio.h>
#include <string.h>
struct flag 
{
	unsigned int a : 2;  //32λ    11   //3
	unsigned int b : 3;	 //111			//7
	unsigned int c : 4;	 //1111			//15
	unsigned int d : 4;	 //1111			//15
};
int main() 
{
	struct flag myFlag = { 3,8,17,15 };  超过之后从0开始
	printf("%d\t%d\t%d\t%d\n", myFlag.a, myFlag.b, myFlag.c, myFlag.d);
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值