函数指针与指针函数练习讲解
练习1:
char *ptr;
if ((ptr = (char *)malloc(0)) == NULL)
{
puts("Gota null pointer");
}
else
{
puts("Gota valid pointer");
}
请问指针为NULL时指向哪里,分配的空间为0时又指向哪里?
完整代码:
#include <stdio.h>
#include <stdlib.h>int main() {char* ptr;// 尝试分配0字节内存ptr = (char*)malloc(0);if (ptr == NULL) {puts("Gota null pointer");}else {puts("Gota valid pointer");// 虽然指针有效,但解引用是未定义行为// *ptr = 'A'; // 错误:不要解引用// 可以安全释放free(ptr);}return 0;
}
代码解析:
这段代码主要是调用malloc(0)
来尝试分配 0 字节的内存,然后依据返回值来判断分配是否成功。具体逻辑为:
- 若返回的是
NULL
,就表明分配失败,此时会输出Gota null pointer
。 - 若返回的是一个有效的指针,那就意味着分配成功,会输出
Gota valid pointer
。
练习2:会出现什么问题?
void getmemory(char *p)
{
p=(char *) malloc(100);
strcpy(p,"hello world");
}
int main()
{
char *str=NULL;
getmemory(str);
printf("%s\n",str);
free(str);
return 0;
}
错误分析:
内存泄漏
getmemory
分配的内存地址存储在局部变量p
中,函数返回后该地址丢失,导致内存无法释放。未定义行为
printf("%s\n", str)
尝试打印NULL
指针,以及free(str)
释放NULL
指针(虽然释放NULL
是安全的,但此处逻辑错误)。
解决办法:
正确传递指针
- 使用二级指针
char **p
并传递&str
,或直接返回指针。
- 使用二级指针
内存分配检查
- 始终检查
malloc
的返回值是否为NULL
,避免后续操作空指针。
- 始终检查
修改后的代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>void getmemory(char **p) {*p = (char *)malloc(100);if (*p == NULL) {exit(EXIT_FAILURE);}// snprintf(目标地址, 最大长度, 格式化字符串, 参数...)snprintf(*p, 100, "hello world"); // 自动截断超长内容
}int main() {char *str = NULL;getmemory(&str);printf("%s\n", str);free(str);return 0;
}
运行结果:
练习3:会出现什么问题?
void GetMemory( char *p )
{
p = (char *) malloc( 100 );
}
int main()
{
char *str = NULL;
GetMemory( str );
strcpy( str, "hello world" );
printf( str );
}
错误原因:
指针传递方式错误(内存泄漏)
GetMemory
函数通过值传递接收指针p
,这意味着函数内部对p
的修改(如分配内存)不会影响外部的str
指针。因此,main
中的str
仍然是NULL
,而malloc
分配的内存地址被丢弃,导致内存泄漏。空指针解引用(未定义行为)
strcpy(str, "hello world")
尝试向NULL
指针写入数据,这会触发段错误(Segmentation Fault),程序崩溃。
修复:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>void GetMemory(char** p) {*p = (char*)malloc(100);if (*p == NULL) {exit(EXIT_FAILURE);}
}int main() {char* str = NULL;GetMemory(&str);// 只需改这一行!用 snprintf 替代 strcpysnprintf(str, 100, "hello world");printf("%s\n", str);free(str);return 0;
}