【C语言进阶】动态内存管理的面试题||练习
本节内容专门整理了一些动态内存管理的面试题,配有详细的解答。
目录
1. 看代码说结果
2. 看代码说结果
3. 看代码说结果
4.小乐乐与欧几里得
描述
分析1:
分析2:
代码:
5. 空心正方形
分析:
1. 看代码说结果
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>char* GetMemory(void)
{char p[] = "hello world";return p;
}
void Test(void)
{char* str = NULL;str = GetMemory();printf(str);
}int main()
{ Test();return 0;
}
这里会报错,这是常见的野指针错误;首先调用Test函数再调用GetMemory函数,然后将字符串赋给p数组,执行完毕后p所指向的区域会进行销毁,但是返回了p的地址,对野指针进行解引用一定会出错。
这里举一个例子,涉及到函数栈帧的知识点,之后会单独做一期来进行讲解函数栈帧。
正常情况下这里的p是一个野指针,这是因为p指向的空间已经被回收了,这时候调用printf,就会创建一个函数栈帧在main函数之上,在原来已经被销毁的test函数的位置,所以在test的内部的变量a一定会被覆盖,最后会打印出其他值;
如果没有hehe的输出,这里在内存没有被覆盖的情况下有几率会打印出10。
2. 看代码说结果
这段代码可以正常输出hello,存在一个问题就是没有手动释放内存空间,需要在输出之后加上:
free(str);
str = NULL;
3. 看代码说结果
str并没有置为空,所以这是一个野指针的问题,这段代码将已经回收的内存重新覆盖新的值,这属于非法访问已经释放的内存,所以虽然可以打印world,但是逻辑上是不允许的。
需要再free的后面加上:
str = NULL;
下面给一段代码,来根据代码了解内存区域:
首先全局变量和静态变量存放在数据段(全局区)之中;
局部变量是存放在栈区中;
字符串常量存放在代码段(常量区)中;
使用malloc开辟的空间是在堆区中;
4.小乐乐与欧几里得
描述
小乐乐最近在课上学习了如何求两个正整数的最大公约数与最小公倍数,但是他竟然不会求两个正整数的最大公约数与最小公倍数之和,请你帮助他解决这个问题。
输入描述:
每组输入包含两个正整数n和m。(1 ≤ n ≤ 109,1 ≤ m ≤ 109)
输出描述:
对于每组输入,输出一个正整数,为n和m的最大公约数与最小公倍数之和。
示例1
输入:
10 20
输出:
30
分析1:
最大公约数:可以从这两个数中的较小值出发,逐步递减;
最小公倍数:可以从这两个数中的较大值出发,逐步递增。
分析2:
上面的方法整体效率太低了,我们开始想想另外一个办法 :辗转相除法。
n % m 余数若不为0,那么r赋给m,m赋给n,继续相余,如果得数是0,此时我们的最大公约数就是m。
此时最小公倍数是(n * m) / 最大公约数。
这里需要注意的是数字的范围,所以可以给定长整型。
代码:
#include <stdio.h>
/*
思路:
1、使用辗转相除法求出最大公约数。
2、两个数相乘再除以最大公约数就是最小公倍数。
3、输出记得使用长整型。*/
int main() {long n = 0,m = 0;while( scanf("%ld %ld",&n,&m) == 2){long i = n;long j = m;long r = 0;// 计算最大公约数while(r = i % j){i = j;j = r; }// 跳出循环j就是最大公约数// 计算最小公倍数r = (m * n) / j;printf("%ld\n", r + j);}return 0;
}
5. 空心正方形
KiKi学习了循环,BoBo老师给他出了一系列打印图案的练习,该任务是打印用“*”组成的“空心”正方形图案。
输入描述:
多组输入,一个整数(3~20),表示输出的行数,也表示组成正方形边的“*”的数量。
输出描述:
针对每行输入,输出用“*”组成的“空心”正方形,每个“*”后面有一个空格。
示例1
输入
4
输出
* * * * * * * * * * * *
分析:
我们可以先按照打印二维数组打印“* ”,这样我们会得到一个正方形,当我们需要空心的时候,只需要判断当行数为0或者为总行数-1的时候 或者 列数为0或者总列(行)数-1的时候打印* ,其余时候打印两个空格即可。
#include <stdio.h>int main() {int a = 0;while(scanf("%d", &a) == 1){int i = 0;for (i = 0; i < a; i++) {int j = 0;for (j = 0; j < a; j++) {if (i == 0 || i == (a-1) ||j == 0 || j == (a-1) ) {printf("* ");}else{printf(" ");}}printf("\n");}}return 0;
}