C语言-柔性数组与几道动态内存相关的经典笔试题(12.2)

news2024/11/21 2:26:31

目录

思维导图:

1.柔性数组

1.1柔性数组的特点

1.2柔性数组的使用

1.3柔性数组的优势

2.几道经典笔试题

2.1题目1

2.2题目2

2.3题目3

2.4题目4

写在最后:


思维导图:

1.柔性数组

1.1柔性数组的特点

例:

#include <stdio.h>

typedef struct S
{
	int n;
	char arr[];//大小是未知的//这是柔性数组成员
}S;

int main()
{
	printf("&d\n", sizeof(S));//不计算大小
}

输出:

输出:4

柔性数组的特点:

1.结构中的柔性数组成员前面必须至少一个其他成员。

2.sizeof 返回的这种结构大小不包括柔性数组的内存。

3.包含柔性数组成员的结构用malloc函数进行内存的动态分配,

并且分配的内存应该大于结构的大小,以适应柔性数组的预期大小。

1.2柔性数组的使用

例:

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

typedef struct S
{
	int n;
	char arr[];//大小是未知的
}S;

int main()
{
	//开辟
	S* ps = (S*)malloc(sizeof(S) + 10 * sizeof(char));//结构体大小+柔性数组需要的大小

	//判断
	if (ps == NULL)
	{
		perror("malloc");
		return 1;
	}

	//使用
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		ps->arr[i] = 'Q';
		printf("%c ", ps->arr[i]);
	}
	//增容
	//.....

	//释放
	free(ps);
	ps = NULL;
	return 0;
}

输出:

输出:Q Q Q Q Q Q Q Q Q Q

1.3柔性数组的优势

其实柔性数组能实现的操作,利用指针也能实现:

例:

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

typedef struct S
{
	int n;
	char* arr;
}S;

int main()
{
	//开辟内存空间
	S* ps = (S*)malloc(sizeof(S));
	if (ps == NULL)
	{
		return 1;
	}
	ps->n = 100;
	ps->arr = (char*)malloc(sizeof(char) * 10);
	if (ps->arr == NULL)
	{
		perror("malloc:");
		return 1;
	}

	//使用
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		ps->arr[i] = 'Q';
		printf("%c ", ps->arr[i]);
	}

	//增容
	char*ptr=(char*)realloc(ps->arr, 20 * sizeof(char));
	if (ptr != NULL)
	{
		ps->arr = ptr;
	}
	else
	{
		perror("realloc");
		return 1;
	}

	//释放
	free(ps->arr);
	ps->arr = NULL;
	free(ps);
	ps = NULL;
	return 0;
}

输出:

输出:Q Q Q Q Q Q Q Q Q Q

但是用柔性数组实现更好一些:

1.使用柔性数组方便内存的释放,只需要一次free。

2.连续的内存有益于提高访问速度,也有益于减少内存碎片。

总而言之,柔性数组给我们解决问题提供了更多的可能。

2.几道经典笔试题

2.1题目1

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

void GetMemory(char* p)
{
	p = (char*)malloc(100);//申请内存地址
}//p变量销毁了,malloc空间未释放,导致内存泄漏

void test()
{
	char* str = NULL;
	GetMemory(str);
	strcpy(str, "hello world");//访问的是0地址//不允许访问//程序崩溃
	printf(str);
}

注:记得及时释放开辟的动态内存。

正确的写法:

我们可以通过传值调用使传过去的指针指向开辟动态内存。

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

//正确的写法
void GetMemory(char** p)
{
	*p = (char*)malloc(100);//申请内存地址
}

void test()
{
	char* str = NULL;
	GetMemory(&str);//传址调用
	strcpy(str, "hello world");
	printf(str);
	//释放
	free(str);
	str = NULL;
}

int main()
{
	test();
	return 0;
}

输出:

输出:hello world

当然,也可以通过函数返回值的形式,

将指向动态内存空间的指针返回:

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

//更多的方法
char* GetMemory()
{
	char*p = (char*)malloc(100);//申请内存地址
	return p;//返回地址
}

void test()
{
	char* str = NULL;
	str = GetMemory();
	strcpy(str, "hello world");
	printf(str);
	//释放
	free(str);
	str = NULL;
}

int main()
{
	test();
	return 0;
}

输出:

输出:hello world

2.2题目2

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

char* GetMemory()
{
	char p[] = "hello world";
	return p;//返回栈空间的地址
}//p数组销毁了

void test()
{
	char* str = NULL;
	str = GetMemory();
	printf(str);//非法访问	
}

int main()
{
	test();
	return 0;
}

注 :不要访问没有开辟的内存空间,非常危险。

再看一个类似的例子:

#include <stdio.h>

//类似的问题
int* test()
{
	int a = 0;
	return &a;
}//int a的空间被销毁了

int main()
{
	int* p = test();
	printf("hehe\n");//栈区中原本存放a变量的空间被覆盖了
	printf("%d\n", *p);//打印随机值(非法访问)
	return 0;
}

输出:

输出:5

最后就输出了个随机值。

2.3题目3

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

void GetMemory(char** p, int num)
{
	*p = (char*)malloc(num);//开辟空间
}

void Test(void)
{
	char* str = NULL;
	GetMemory(&str, 100);//传址调用

	//使用
	strcpy(str, "hello");
	printf(str);

	//我们发现它没有释放内存//导致内存泄漏
}

注:一定要记得释放内存!

2.4题目4

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

void test()
{
	char* str = (char*)malloc(100);//开辟空间
	strcpy(str, "hello");
	free(str);//str释放了
	if (str != NULL)//str被释放后已经是野指针了
	{
		strcpy(str, "world");//非法访问
		printf(str);
	}
}

int main()
{
	test();
	return 0;
}

指针释放后再使用会导致野指针。

我们可以改进这段代码:

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

void test()
{
	char* str = (char*)malloc(100);//开辟空间
	strcpy(str, "hello");
	free(str);//str释放了
	str = NULL;//主动置为空才行
	if (str != NULL)
	{
		strcpy(str, "world");//非法访问
		printf(str);
	}
}

这样就不会出错了。

写在最后:

以上就是本篇文章的内容了,感谢你的阅读。

如果喜欢本文的话,欢迎点赞和评论,写下你的见解。

如果想和我一起学习编程,不妨点个关注,我们一起学习,一同成长。

之后我还会输出更多高质量内容,欢迎收看。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/162779.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

javaEE 初阶 — java对于的操作文件

文章目录1. File 类概述2. 代码示例2.1 示例1&#xff1a;以绝对路径为例&#xff0c;演示获取文件路径2.2 示例2&#xff1a;以相对路径为例&#xff0c;演示获取文件路径2.3 示例3&#xff1a;测试文件是否存在、测试是不是文件、测试是不是目录2.4 示例4&#xff1a;创建文件…

27.函数指针变量的定义, 调用函数的方法,函数指针数组

函数指针变量的定义 返回值类型&#xff08;*函数指针变量名&#xff09;&#xff08;形参列表&#xff09;; int( *p )( int , int );//定义了一个函数指针变量p&#xff0c;p指向的函数必须有一个整型的返回值&#xff0c;有两个整型参数。 int max(int x, int y) { } int m…

AMR-IE:一种利用抽象语义表示(AMR)辅助图编码解码的联合信息抽取模型

Abstract Meaning Representation Guided Graph Encoding and Decoding for Joint Information Extraction 论文&#xff1a;2210.05958.pdf (arxiv.org) 代码&#xff1a;zhangzx-uiuc/AMR-IE: The code repository for AMR guided joint information extraction model (NAAC…

【学习笔记】【Pytorch】七、卷积层

【学习笔记】【Pytorch】七、卷积层学习地址主要内容一、卷积操作示例二、Tensor&#xff08;张量&#xff09;是什么&#xff1f;三、functional.conv2d函数的使用1.使用说明2.代码实现四、torch.Tensor与torch.tensor区别五、nn.Conv2d类的使用1.使用说明2.代码实现六、卷积公…

C/C++ noexcept NRVO

为什么需要noexcept为了说明为什么需要noexcept&#xff0c;我们还是从一个例子出发&#xff0c;我们定义MyClass类&#xff0c;并且我们先不对MyClass类的移动构造函数使用noexceptclass MyClass { public:MyClass(){}MyClass(const MyClass& lValue){std::cout << …

使用语雀绘制 Java 中六大 UML 类图

目录 下载语雀 泛化关系&#xff08;Generalization&#xff09; 实现关系&#xff08;Realization&#xff09; 关联关系&#xff08;Association&#xff09; 依赖关系&#xff08;Dependency&#xff09; 聚合关系&#xff08;Aggregation&#xff09; 组合关系&…

【Python学习】列表和元组

前言 前四天每天更新了小白看的基础教程 今天开始就更新一下&#xff0c;深入一点的知识点吧 还是老话&#xff1a;刚接触python的宝子可以点击文章末尾名片进行交流学习的哦 什么是列表和元组 列表是动态的&#xff0c;长度大小不固定&#xff0c;可以随意地增加、删减或…

【软件测试】软件测试基础2

1. 软件测试的生命周期 软件测试的生命周期&#xff1a; 需求分析→测试计划→ 测试设计、测试开发→ 测试执行→ 测试评估 ● 需求分析&#xff1a;站在用户的角度&#xff1a;查看需求逻辑是否正确&#xff0c;是否符合用户的需求和行为习惯&#xff1b;站在开发人员的角度&…

Nexus使用

环境 apache-maven-3.5.4nexus-3.38.1-01 Android开发中常用的maven代理地址 阿里云&#xff1a;http://maven.aliyun.com/nexus/content/groups/public/google&#xff1a;https://dl.google.com/dl/android/maven2/jcenter&#xff1a;https://jcenter.bintray.com/mavenC…

Leetcode:236. 二叉树的最近公共祖先(C++)

目录 问题描述&#xff1a; 实现代码与解析&#xff1a; 原理思路: 问题描述&#xff1a; 给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。 百度百科中最近公共祖先的定义为&#xff1a;“对于有根树 T 的两个节点 p、q&#xff0c;最近公共祖先表示为一个节点 x&…

Xmanager7远程登录ubuntu20.04

Xmanager7远程登录ubuntu20.04 本文不介绍Xmanager7的下载和安装方法&#xff0c;详细内容可以参考【实用软件】Xmanager 7.0安装教程 - 哔哩哔哩 (bilibili.com)。关于Xmanager7远程登录的教材参考于 (149条消息) Xmanager远程桌面教程_周先森爱吃素的博客-CSDN博客_xmanage…

代码随想录第60天|84.柱状图中最大的矩形

84.柱状图中的最大的图形 总体思路&#xff1a;找到左右两个方向第一个小于该柱子高度的下标&#xff0c;用右下标-左下标-1得到该柱子高度对应的宽度w,再用宽度w*高度h得到面积&#xff0c;返回面积最大值 双指针法&#xff08;超时&#xff09; for循环判断左右第一个小于…

【NI Multisim 14.0虚拟仪器设计——虚拟仪器的引入】

目录 序言 前言 &#x1f349;知识点 一、虚拟仪器的引入 &#x1f34a;1.工具栏 &#x1f34a; 2.基本操作 ①仪器的选用与连接 ②仪器参数的设置 序言 NI Multisim最突出的特点之一就是用户界面友好。它可以使电路设计者方便、快捷地使用虚拟元器件和仪器、仪表进行电…

Linux云服务器下的gitee提交代码方法

目录 创建一个gitee仓库 gitee提交代码三板斧 1. git add 提交的文件 2. git commit -m "提交日志" 3. git push 可能存在的问题 .gitignore介绍 如何删除文件 创建一个gitee仓库 gitee提交代码三板斧 1. git add 提交的文件 作用&#xff1a;添加我…

Electron + React 应用打包全流程

&#xff08;第一次用 Typora 写博&#xff0c;希望效果不错~&#xff09; 这几天有个创意编程比赛&#xff0c;要写一个电脑端应用。我准备用 React.js Electron 做&#xff08;因为熟悉~&#xff09;&#xff0c;编程部分一路风雨无阻&#xff0c;到了打包却出现了问题。El…

多轮对话(一):概述(意图识别+槽填充)

一、对话系统 基于流水线的面向任务的对话系统包含了四个关键部分&#xff1a; 语言理解。它被称为自然语言理解&#xff08;NLU&#xff09;&#xff0c;它把用户话语解析为预定义的语义槽。对话状态跟踪器。它管理每一轮的输入与对话历史&#xff0c;输出当前对话状态。对话…

Sechunter移动应用隐私合规检测详解

概述&#xff1a; 受益于移动设备的广泛普及&#xff0c;移动应用近年来得到了蓬勃发展。基于移动设备集成的各类传感器&#xff0c;众多功能丰富的移动应用被开发出来&#xff0c;聚集了大量高价值用户隐私数据&#xff0c;包括用户身份信息、地理位置信息、账户资料信息等。…

玩转机密计算从 secGear 开始

随着网络与计算业务的快速发展&#xff0c;数据成为数字经济的关键生产要素&#xff0c;如何高质量挖掘数据价值&#xff0c;构建安全、合规、可信的数据流通&#xff0c;成为推动数字经济健康发展的关键。此外&#xff0c;根据我国个人信息保护法、欧盟通用数据保护条例 GDPR …

IDEA安装使用代码提交模板

IDEA安装使用代码提交模板 1. idea安装git commit template插件 2、重启idea 3、选择要提交的文件右击&#xff08;或CtrlShiftK&#xff09;&#xff0c;如下图&#xff1a; 3.1 Type of change用于说明commit的类别,常用的标识如下&#xff1a; feat: 新功能&#xff08;f…

501. 二叉搜索树中的众数

501. 二叉搜索树中的众数 难度简单 给你一个含重复值的二叉搜索树&#xff08;BST&#xff09;的根节点 root &#xff0c;找出并返回 BST 中的所有 众数&#xff08;即&#xff0c;出现频率最高的元素&#xff09;。 如果树中有不止一个众数&#xff0c;可以按 任意顺序 返…