IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> C语言--这几道经典笔试题,你能一眼看出陷阱吗? -> 正文阅读

[C++知识库]C语言--这几道经典笔试题,你能一眼看出陷阱吗?

题目1

问:
有如下代码,Test()函数的运行结果如何?

void GetMemory(char* p)
{
	p = (char*)malloc(100);
}
void Test(void)
{
	char* str = NULL;
	GetMemory(str);//值传参
	strcpy(str, "hello world");
	printf(str);
}

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

结果:
这条代码会运行出结果,但是并不会和我们预想的一样打印出“hello world”,而是一片空白。

存在问题:

  1. 在Test()函数中,虽然str是一个指针变量,但是调用GetMemory进行传参时,传过去的只是str这个指针变量的值,也就是说这是一次值传递。因此在GetMemory函数内部,给它的形参p开辟了一块空间,但是对函数外部的str指针并没有任何影响,当程序回到Test函数中时,str仍是一个空指针NULL,因此strcpy会失败,自然也就不会打印出任何东西了。
  2. GetMemory函数中给p在堆区上开辟出的动态内存空间在该函数销毁后也没有释放,这导致了内存泄漏!

修改之后:
这段代码的修改有多种方法,可以参考以下两种:

  1. GetMemory函数修改为有返回值,在Test函数最后释放动态内存空间:
char* GetMemory(char* p)
{
	p = (char*)malloc(100);
	return p;
}
void Test(void)
{
	char* str = NULL;
	str = GetMemory(str);//接收返回值
	strcpy(str, "hello world");
	printf(str);
	free(str);//释放
	str = NULL;
}
  1. GetMemory函数传参时使用地址传参,即Test函数内将&str传过去,GetMemory函数形参使用二级指针接收str地址。在Test函数最后释放动态内存空间:
void GetMemory(char** p)//二级指针
{
	*p = (char*)malloc(100);//注意要解引用一次
}
void Test(void)
{
	char* str = NULL;
	GetMemory(&str);//地址传参
	strcpy(str, "hello world");
	printf(str);
	free(str);//释放
	str = NULL;
}

题目2

问:
有如下代码,Test()函数的运行结果如何?

char* GetMemory(void)
{
	char p[] = "hello world";
	return p;
}
void Test(void)
{
	char* str = NULL;
	str = GetMemory();
	printf(str);
}
int main()
{
	Test();
	return 0;
}

结果:
运行后,打印出来的是一些乱码,而非预期的hello world。

存在问题:
这段代码和上面的代码的修改1很相似,但是为什么这里出现问题了呢?

这段代码本质上是局部变量的生命周期问题。GetMemory函数中创建的p数组,是创建在栈区上的一个只存活于该函数内部的局部变量,当程序结束GetMemory函数后,在该函数内部创建的空间也都随之销毁。虽然传回了一个地址,但是该地址指向的空间的内容已经被销毁了,可能已经被其他内容占据,因此此处无法正确打印出hello world。

修改之后:
这里可以直接和题目1中一样,使用堆区动态空间。
也可以在调用GetMemory函数时进行传参。如下:

char* GetMemory(char pa[])
{
	pa = "hello world";
	return pa;
}
void Test(void)
{
	char* str = NULL;
	char p[] = { 0 };
	str = GetMemory(p);
	printf(str);
}

题目3

问:
有如下代码,Test()函数的运行结果如何?

void GetMemory(char** p, int num)
{
	*p = (char*)malloc(num);
}
void Test(void)
{
	char* str = NULL;
	GetMemory(&str, 100);
	strcpy(str, "hello");
	printf(str);
}

存在问题:
此题其实和题目1一样,一眼可以看出没有free释放动态内存。其修改可参见题目1。


题目4

问:
请问运行Test 函数会有什么样的结果?

void Test(void)
{
	 char *str = (char *) malloc(100);
	 strcpy(str, "hello");
	 free(str);
	 if(str != NULL)
 	{
		 strcpy(str, "world");
		 printf(str);
 	}
}

存在问题:
这段代码映入眼帘的可能是free的位置,有的同学或许会觉得是free释放太早。但重点并非如此,而是在free释放完动态空间后没有及时对动态空间的指针进行置空处理。

切记:用完动态内存开辟的空间之后一定要进行free释放,释放后再手动进行置空处理。

修改之后:

void Test(void)
{
	 char *str = (char *) malloc(100);
	 strcpy(str, "hello");
	 free(str);
	 str = NULL;//置空
	 if(str != NULL)
 	{
		 strcpy(str, "world");
		 printf(str);
 	}
}


题目5

问:
以下代码存在什么问题:

int* myFun()
{
	int* str;
	int a = 10;
	str = &a;
	return str;
}

分析:
这段代码主要存在野指针的问题。
str定义时没有初始化,我们不知道它指向哪里,贸然使用有安全问题。

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-04-04 11:50:13  更:2022-04-04 11:54:07 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 1:07:03-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码