本篇博客介绍关于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;
}