012-堆,结构体

012-堆,结构体

堆空间的申请和释放

堆空间特点?

​ 栈空间的特点是,自动申请自动释放
​ 堆空间由用户自己主动申请,主动释放
​ 利用函数malloc进行堆空间的申请
​ 利用函数free进行堆空间使用完毕后的释放

问题:

​ 局部变量的存储空间在栈区;
​ 全局变量的存储空间在data/bss区;
​ 区别是有初始化data,无初始化bss;
​ 常量字符串的存储空间在rodata区;
​ 通过malloc申请的空间在堆区;

如何申请堆空间?如何释放空间?

​ 函数malloc用来申请堆空间
​ 函数free用来释放堆空间

#include <stdlib.h>

void *malloc(size_t size);
void free(void *ptr);

参数:
​ size:用来向系统表明将要申请的堆空间的大小
​ 单位字节
返回值:
​ 成功时,返回申请的堆空间的首地址
​ 失败时,返回NULL

参数:
​ ptr:申请的堆空间的地址

注意:
​ 释放时,必须释放的是申请的堆空间

注意:
​ 对空间申请成功时,会被初始化为0
​ 释放时,首个类型空间会被初始化0

例子:
int a[10];
想要申请一块和a一样的堆空间,怎么办?
malloc(sizeof(a));
或者
malloc(sizeof(int)*10);
或者
malloc(4*10);

int *p = (int *)malloc(40);
申请了一块40字节的堆空间进行使用
把malloc的返回值强制类型转换成int *
就相当于把malloc申请的空间切割成一个又一个的4字节空间进行使用
		
char *q = (char *)p;
请指出下面每一行代码的含义,如果有错误,则说明原因?
1char A[10] = "hello";  
在栈区连续申请10个字节,然后使用变量A间接访问这片内存空间。
在常量区连续申请6个字节,然后存放着字符串hello。
然后将常量区的hello拷贝到A所对应的空间上。

strcpy(A,"world");  
在常量区连续申请6个字节,然后存放字符串world
将常量区的字符串world复制到地址A所在的存储空间上

2char *p = "hello";
在常量区连续申请6个字节,然后存放字符串hello
在栈区连续申请4个字节,然后使用变量p间接访问这片存储空间
用来存放一个char型地址值
然后将常量区的hello的首元素h的地址存放在p的存储空间上

以下两句有问题:
		strcpy(p,"world");
		在常量区连续申请6个字节,然后存放字符串world
		将常量区的字符串world复制到指针p所指向的存储空间上
		该语句写法正确,但是意义错误
		因为常量区不能被更改

	*p = "world";
	在常量区连续申请6个字节,然后存放字符串world
	表示的意义是想把字符串world放在p所指向的地址空间上
	但是类型上不匹配

	p = "world";
	在常量区连续申请6个字节,然后存放字符串world
	使char型指针p重新指向一个新的常量字符串,是可以的

3char A[10];  
在栈去连续申请10个字节,然后使用变量A间接访问这块存储空间 
A这块空间没有进行初始化,所以是随机内容

strcpy(A,"hello"); 
在常量区连续申请6个字节,然后存放字符串hello
将常量区的字符串hello复制到地址A所在的存储空间上

4char A[10]; 
在栈去连续申请10个字节,使用变量A间接访问这块存储空间
        
char *p = A; 
在栈区连续申请4个字节,使用变量p间接访问这块存储空间 
用来存放一个char型的地址值
A在这里表示数组A的首元素的地址
使char型指针p指向数组A的首元素的地址

strcpy(p,"hello"); 
在常量区连续申请6个字节,然后存放字符串hello
将常量区的字符串hello复制到地址p所指向的地址空间上
即是数组A的存储空间

5char A[10]; 
在栈区连续申请10个字节,然后使用变量A间接访问这块存储空间
数组A的存储空间中的数据是随机的

char *p = A;
在栈区连续申请4个字节,使用变量p间接访问这块存储空间 
用来存放一个char型的地址值
A在这里表示数组A的首元素的地址
使char型指针p指向数组A的首元素的地址

p = "hello";
在常量区连续申请6个字节,然后存放字符串hello
使char型指针p重新指向一个新的常量字符串,是可以的

6char *p = malloc(sizeof(char)*10);  
在堆区申请一块连续的10字节大小的存储空间
在栈去申请一块连续的4字节大小的存储空间,使用p间接访问该块空间
然后使用p访问对应空间,保存申请的堆空间的首地址

p = "hello";
在常量区连续申请6个字节,然后存放字符串hello
使char型指针p重新指向一个新的常量字符串,是可以的

7char *p = malloc(sizeof(char)*10);
在堆区申请一块连续的10字节大小的存储空间
在栈去申请一块连续的4字节大小的存储空间,使用p间接访问该块空间
然后使用p访问对应空间,保存申请的堆空间的首地址

strcpy(p,"hello");
在常量区连续申请6个字节,然后存放字符串hello
将常量区的字符串hello复制到地址p所指向的地址空间上
即是申请的堆空间

结构体:

什么是结构体?
  • 不同变量类型的集合
  • 当目标比较复杂,需要多维的数据进行描述时
  • 进行结构体类型的定义打包,方便对某一个体的信息进行统一管理
结构体可以包含什么类型?
  • ​ 基本数据类型:
    ​ char/short/int/long/float/double
  • ​ 复合类型:
    ​ 数组 - 整型数组/字符数据、、、
    ​ 指针数组
    ​ 结构体数组
    ​ 指针 - 整型指针/字符指针、、、
    ​ 数组指针/函数指针
    ​ 结构体指针
    ​ 函数?
    ​ 不能
怎样定义结构体类型?

格式:

struct 结构体类型名
{
    char a;
    short b;
    int c;
    long d;
    float e;
    double f;

    int g[5];
    char *h;

    int (*i)();
    ...
        ...
}

​ 理解:
​ 结构体类型是被自由定义
​ (struct 结构体类型名)就相当于int、char、、、
​ 它可以被认为是一种的新的自定义的变量类型

​ 例子:

struct stu	//用来描述学生的相关信息
{
    char name[20];
	char sex[6];	//man/woman
	int year;
	char num[20];
};
(struct stu)将被视为一种新的变量类型,由自定义而成
结构体的大小怎么算?

在这里插入图片描述

由结构体内的所有成员共同决定;

例子:

struct stu
{
    char name[20];		//20字节  20
    char sex[6];		//6字节   8
    int year;			//4字节   4
    char num[20];		//20字节  20
};
请问sizeof(struct stu)=?	52

struct a
{
    char a[5];//5	8
    int b;    //4	4
    char c;   //1	4
    int d;    //4	4
    short e;  //2	4
};
请问sizeof(struct a)=? 24

struct b
{
    int a;       //4  8(64bit)
    long long b; //8  8
};
请问sizeof(struct b)=?   12	32bit
    				    16	 64bit

struct c
{
    long long b;
    int a;	
};
请问sizeof(struct c)=?  12	32bit
    				   16	 64bit
练习:
struct temp
{
	char a[4];  //4  4
	short b[2]; //4  4
	char c;     //1  2(最大类型是short,所以补2即可)
	short d;    //2  2
	char e;     //1  2(最大类型是short,所以补2即可)
};
sizeof(struct temp)=?		14
怎样定义结构体变量?

例子:

struct stu
{
    char name[20];		//20字节
    char sex[6];		//6字节
    int year;			//4字节
    char num[20];		//20字节
};
声明一个对应结构体类型的变量
    格式:
    结构体类型+变量
    例子:
    struct stu student_1;
student_1就是对应的(struct stu)类型的结构体变量
怎样定义结构体指针变量?

例子:

struct stu
{
    char name[20];		//20字节
    char sex[6];		//6字节
    int year;			//4字节
    char num[20];		//20字节
};
声明一个对应结构体类型的指针变量
    格式:
    结构体类型+*+变量
    例子:
    struct stu *p;
p就是对应的(struct stu)类型的结构体指针
怎样访问结构体成员?

​ 1.
​ 利用结构体的变量
​ 首先需要定义一个结构体类型变量
​ 想要访问结构体的成员变量时
​ 需要与结构体类型变量产生联系
​ 格式:
​ 结构体变量名.结构体的成员变量名
​ 例子:

struct stu student_1;

stpcpy(student_1.name,"张三");
stpcpy(student_1.sex,"男");
student_1.year = 20;
stpcpy(student_1.num,"110119120");	

​ 2
​ 利用结构的指针变量
​ 2.1
​ 首先需要定义一个结构体类型变量
​ 其次需要定义一个结构体类型指针变量
​ 且使结构体指针变量指向结构体普通变量
​ 想要访问结构体的成员变量时
​ 需要与结构体类型变量产生联系
​ 格式:
​ 结构体指针变量名->结构体的成员变量名
​ 例子:

struct stu student_1;
struct stu *p = &student_1;

stpcpy(p->name,"张三");
stpcpy(p->sex,"男");
p->year = 20;
stpcpy(p->num,"110119120");

​ 2.2
​ 首先需要定义一个结构体类型变量
​ 其次需要定义一个结构体类型指针变量
​ 且使结构体指针变量指向为结构体申请的一块连续的堆空间
​ 想要访问结构体的成员变量时
​ 需要与结构体类型变量产生联系
​ 格式:
​ 结构体指针变量名->结构体的成员变量名
​ 例子:

struct stu student_1;
struct stu *p = (struct stu *)malloc(sizeof(struct stu));
				
stpcpy(p->name,"张三");
stpcpy(p->sex,"男");
p->year = 20;
stpcpy(p->num,"110119120");

​ 总结:
​ 指针的指向必须有意义才能被使用
​ 写程序是注意观察指针使用前的指向

结构体初始化

​ 1.相同类型的结构体变量可以直接进行整体赋值;

​ 2.定义对应的结构体类型变量时可直接进行整体初始化;

​ 3.定义对应的结构体类型变量时可进行部分初始化;
​ 按顺序对目标量进行初始化赋值;
​ 未进行初始化赋值的结构体成员变量将被初始化为0;

​ 4.不建议在定义对应的结构体类型变量时进行针对性的初始化;

练习:

​ 定义个结构体,表示学生成绩档案
​ 包括姓名、学号、语文成绩、数学成绩、英语成绩
​ 以上数据均通过键盘进行输入

为5个学生进行数据输入
数据输入完毕之后打印查看

功能:
1.可通过学号或姓名查看指定目标的相关成绩
2.可指定查看对应学科或总分的排名
3.可查看对应学科或总分的平均分

参考答案:

#include<stdio.h>
#include <strings.h>

struct stu
{
	char name[20];
	char id[20];
	int yw;
	int sx;
	int yy;
};

struct stu stu[5];
	
int switch_1()
{
	char buf[20];
	int i;
		
	switch(1)
	{
		printf("请输入查询目标的姓名或学号\n");
		bzero(buf,sizeof(buf));
		scanf("%s",buf);
		
		for(i=0;i<5;i++)
		{
			if(!strcmp(buf,stu[i].name))
			{
				printf("名字:%s",stu[i].name);
				printf("学号:%s",stu[i].id);
				printf("语文成绩:%s",stu[i].yw);
				printf("数学成绩:%s",stu[i].sx);
				printf("英语成绩:%s",stu[i].yy);
				break;
			}
			if(!strcmp(buf,stu[i].id))
			{
				printf("名字:%s",stu[i].name);
				printf("学号:%s",stu[i].id);
				printf("语文成绩:%s",stu[i].yw);
				printf("数学成绩:%s",stu[i].sx);
				printf("英语成绩:%s",stu[i].yy);
				break;
			}
		}
		
		if(!strcmp,0)
		{
			break;
		}
		
	}
}

int main()
{

	int i;
	for(i=0;i<5;i++)
	{
		bzero(&stu[i],sizeof(stu[i]));
		
		printf("请输入名字:");
		scanf("%s",student[i].name);
		
		printf("请输入学号:");
		scanf("%s",student[i].id);
		
		printf("请输入语文成绩:");
		scanf("%f",&student[i].yw);
		
		printf("请输入数学成绩:");
		scanf("%f",&student[i].sx);
		
		printf("请输入英语成绩:");
		scanf("%f",&student[i].yy);
	}
	for(i=0;i<5;i++)
	{
		printf("名字:%s",stu[i].name);
		printf("学号:%s",stu[i].id);
		printf("语文成绩:%s",stu[i].yw);
		printf("数学成绩:%s",stu[i].sx);
		printf("英语成绩:%s",stu[i].yy);
	}
	int n;
	switch(1)
	{
		printf("0.结束查询\n");
		printf("1.可通过学号或姓名查看指定目标的相关成绩\n");
		printf("2.可指定查看对应学科或总分的排名\n");
		printf("3.可查看对应学科或总分的平均分\n");
		printf("请输入对应编号,使用相关功能\n");
		scanf("%d",&n);
		
		if(0==n)
		{
			break;
		}
		
		switch(n)
		{
			case 1:
				switch_1();
				break;
			case 2:
			case 3:
		}
	}
}
}
for(i=0;i<5;i++)
{
	printf("名字:%s",stu[i].name);
	printf("学号:%s",stu[i].id);
	printf("语文成绩:%s",stu[i].yw);
	printf("数学成绩:%s",stu[i].sx);
	printf("英语成绩:%s",stu[i].yy);
}
int n;
switch(1)
{
	printf("0.结束查询\n");
	printf("1.可通过学号或姓名查看指定目标的相关成绩\n");
	printf("2.可指定查看对应学科或总分的排名\n");
	printf("3.可查看对应学科或总分的平均分\n");
	printf("请输入对应编号,使用相关功能\n");
	scanf("%d",&n);
	
	if(0==n)
	{
		break;
	}
	
	switch(n)
	{
		case 1:
			switch_1();
			break;
		case 2:
		case 3:
	}
}

}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Three笔记

有用的话赏点吧

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值