动态内存管理-练习
1请问运行Test 函数会有什么样的结果?
void GetMemory(char *p)
{
p = (char *)malloc(100);//没有free,存在内存泄露的可能
}
void Test(void)
{
char *str = NULL;
GetMemory(str);
strcpy(str, "hello world");
printf(str);//==printf("%s",str);
}
请问运行Test 函数会有什么样的结果?程序崩溃
改正1
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
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;
}
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;
}
请问运行Test 函数会有什么样的结果?打印随机值,非法访问内存
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);
str = NULL;
}
请问运行Test 函数会有什么样的结果?打印hello,但存在内存泄露
改正
void GetMemory(char **p, int num)
{
*p = (char *)malloc(num);
}
void Test(void)
{
char *str = NULL;
GetMemory(&str, 100);
strcpy(str, "hello");
printf(str);
//忘记释放动态开辟的内存,会导致内存泄露
free(str);
str = NULL;
}
4请问运行Test 函数会有什么样的结果?
void Test(void)
{
char *str = (char *)malloc(100);
strcpy(str, "hello");
free(str);
if (str != NULL)
{
strcpy(str, "world");
printf(str);
}
}
请问运行Test 函数会有什么样的结果?打印world,非法访问内存
改正
void Test(void)
{
char *str = (char *)malloc(100);
strcpy(str, "hello");
free(str);//free释放str指向的空间后,并不会把str置为NULL
str = NULL;
if (str != NULL)
{
strcpy(str, "world");
printf(str);
}
}
找出单身狗
一个数组中只有两个数字是出现一次,其他所有数字都出现了两次
编写一个函数找出这两个只出现一次的数字。
法一
#include <Windows.h>
#include <stdlib.h>
void find_num(int arr[], int sz)
{
int i, j, k = 0;
for (i = 0; i < sz; i++)
{
k = 0;
for (j = 0; j < sz; j++)
{
if (arr[j] == arr[i])
k++;
}
if (k == 1)
printf("单数为 %d\n", arr[i]);
}
printf("\n");
}
int main()
{
int arr[] = { 1, 2, 3, 4, 1, 2, 3, 5 };
int sz = sizeof(arr) / sizeof(arr[0]);
find_num(arr, sz);
system("pause");
return 0;
}
法二:异或
异或运算相同为0,相异为1,则:
a ^ a = 0; (1)
0 ^ a = a; (2)
a ^ b ^ a = b; (3)
1 ^ 2 ^ 1 = 2
2 ^ 2 = 0
0 ^ 3 = 3
将数组里面所有的数字异或一遍,最终得到的那个数字就是只出现一次的数。
//int FindAppearOnce(int arr[], int sz)
//{
// int i = 0;
// int num = 0;
// for (i = 0; i < sz; i++)
// {
// num = arr[i] ^ num;
// }
// return num;
//}
void FindAppearOnce(int arr[], int sz, int* pn1, int* pn2)
{
int num = 0;//记录整组异或的结果,即两个一次出现的数异或的结果
int i = 0;
int k = 1;
for (i = 0; i < sz; i++) //得出整组异或的结果,即两个一次出现的数异或的结果
{
num = num ^ arr[i];
}
while (num & 1 != 1) //找出异或结果中第一个为1的bit位
{
k++;
num = num >> 1;
}
for (i = 0; i < sz; i++)//将原数组分为两组,分别求出每组中出现一次的数字
{
int k_bit = (arr[i] >> (k - 1)) & 1; //arr[i]第k位的值
if (k_bit == 1)
{
*pn1 = *pn1^arr[i];
}
else
{
*pn2 = *pn2^arr[i];
}
}
}
int main()
{
int num1 = 0;
int num2 = 0;
int arr[] = { 1, 2, 3, 4, 5, 1, 2, 3, 4, 8 };
int sz = sizeof(arr) / sizeof(arr[0]);
FindAppearOnce(arr, sz, &num1, &num2);
printf("%d,%d\n", num1, num2);
system("pause");
return 0;
}