本篇博客介绍关于C malloc经典的错误代码写法以及解决方法。
题目1
错误的代码:
#include <iostream>
void test01(char* p)
{
p = (char*)malloc(10);
}
int main1()
{
char* p = NULL;
test01(&p);
const char* str = "hello";
strcpy(p, str);
printf("p= %s", p);
free(p);
return 0;
}
运行结果
出现这种现象,是因为在函数 test01 中,p = (char*)malloc(10); 只是改变了局部变量 p 的值,而不会影响 main 函数中 p 的值,因为 p 是按值传递的。换句话说,main 函数中的 p 仍然是 NULL。修改如下:
void test02(char** p)
{
*p = (char*)malloc(10);
// 在 malloc 后没有检查是否分配成功。
if (*p == NULL)
{
fprintf(stderr, "Memory allocation failed\n");
exit(1);
}
}
将 test01 函数的参数改为 char**,以便通过指针传递并修改 main 中的 p。在 malloc 后添加了内存分配检查,确保内存分配成功。
题目2
错误的代码如下:
#include <iostream>
char* GetMemory()
{
char p[] = "hello world";
return p;
}
int main()
{
char* str = NULL;
str = GetMemory();
printf(str);
return 0;
}
运行结果如下:
在打印str时,输出的并不是“hello world”,这段C++代码存在一个主要的问题:GetMemory 函数返回了一个指向局部变量的指针。局部变量在函数返回后就会被销毁,因此返回指向它们的指针是无效的,会导致未定义行为。
修改如下:
#include <iostream>
char* GetMemory()
{
const char* temp = "hello world";
// 动态分配内存
char* p = (char*)malloc(strlen(temp) + 1);
if (p != NULL)
{
strcpy(p, temp);
}
return p;
}
int main()
{
char* str = GetMemory();
if (str != NULL)
{
printf("%s\n", str);
// 释放动态分配的内存
free(str);
}
else
{
std::cerr << "Memory allocation failed" << std::endl;
}
return 0;
}
输出结果:
上面的代码将 GetMemory 函数改为动态分配内存并返回一个指向动态分配内存的指针。此外,还要确保在 main 函数中释放分配的内存以避免内存泄漏。
另外,在malloc后,尽量加if判断申请的内存是否成功。
题目3
两数交换,错误的代码如下:
#include <iostream>
void swap(int* p1, int* p2)
{
int* p = NULL;
*p = *p1;
*p1 = *p2;
*p2 = *p;
}
int main()
{
int a = 100;
int b = 200;
swap(&a, &b);
printf("a = %d, b = %d\n", a, b);
return 0;
}
运行结果:
在swap函数中,p是一个“野”指针,有可能指向系统区,导致程序运行的崩溃。正确的写法如下:
void swap(int* p1, int* p2)
{
int p;
p = *p1;
*p1 = *p2;
*p2 = p;
}
题目4
将字符串中的小写字母
写法一:
使用标准库函数toupper将小写字母转换为大写字母
#include <stdio.h>
#include <ctype.h>
void ToUpper(char* str)
{
// 遍历字符串中的每个字符
while (*str)
{
// 使用标准库函数toupper将小写字母转换为大写字母
*str = toupper((unsigned char)*str);
str++;
}
}
int main()
{
char str[] = "Hello, World! This is a test.";
printf("Original string: %s\n", str);
ToUpper(str);
printf("Uppercase string: %s\n", str);
return 0;
}
写法二:
通过检查字符的ASCII码值来手动转换小写字母为大写字母。小写字母的ASCII码值范围是97到122(即’a’到’z’),而大写字母的ASCII码值范围是65到90(即’A’到’Z’)。通过减去32,可以将一个小写字母转换为对应的大写字母。
#include <stdio.h>
void ToUpper(char* str)
{
// 遍历字符串中的每个字符
while (*str)
{
// 如果当前字符是小写字母
if (*str >= 'a' && *str <= 'z')
{
// 将其转换为大写字母
*str = *str - ('a' - 'A');
}
str++;
}
}
int main()
{
char str[] = "Hello, World! This is a test.";
printf("Original string: %s\n", str);
ToUpper(str);
printf("Uppercase string: %s\n", str);
return 0;
}