本節內容專門整理了一些動態內存管理的面試題,配有詳細的解答。
目錄
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;
}