函数间传递char指针:两种传参方式是否等价?
关于char指针传参等价性与free/null行为的解读
先把你的MCVE代码补全并整理好(假设MAX_LENGTH定义为100,不影响核心逻辑):
#include <stdlib.h> #include <stdio.h> #include <string.h> #define MAX_LENGTH 100 void passingCharPointer1(char *str) { printf("passingCharPointer1: %s\n", str); str[0] = 'X'; // 修改指向的内容 } void passingCharPointer2(char str[]) { printf("passingCharPointer2: %s\n", str); str[0] = 'Y'; // 修改指向的内容 } int main() { char *str1 = malloc(MAX_LENGTH * sizeof(char)); strcpy(str1, "Hello World"); char *str2 = malloc(MAX_LENGTH * sizeof(char)); strcpy(str2, "Hello StackOverflow"); passingCharPointer1(str1); passingCharPointer2(str2); printf("After passingCharPointer1: %s\n", str1); printf("After passingCharPointer2: %s\n", str2); // 关于free和null的注释部分 free(str1); str1 = NULL; // 为什么要置空? // free(str1); // 这里如果再次free会怎样? free(str2); // str2没有置空,再次free的话? return 0; }
一、两种char指针传参方式完全等价!
在C语言的函数参数列表里,char *str 和 char str[] 是语法糖和本质的关系——编译器会自动把数组形式的参数转换成指针类型。
具体来说:
- 两种写法接收的都是原指针的副本,你可以通过这个副本修改指针指向的内存内容(比如代码里修改字符串首字符,主函数里的原字符串会跟着变);
- 但如果在函数内部修改指针本身(比如
str = malloc(...)),完全不会影响主函数里的原指针,因为你操作的只是个副本; - 哪怕你给数组参数加了长度(比如
char str[100]),编译器也会直接忽略这个长度,照样当成char *str处理。
简单总结:这两种传参写法没有任何功能上的区别,只是写法不同而已。
二、free与NULL的行为详解
咱们逐个看代码里的注释疑问:
free(str1)之后为啥要str1 = NULL?free的作用只是把str1指向的内存还给操作系统,但str1这个变量本身的值(也就是那个内存地址)并没有变——这时候str1就成了野指针,指向的内存已经不属于你的程序了。
把它置为NULL是一种防御性操作:
- 后续如果不小心误操作(比如再次
free或者通过它访问内存),可以通过if (str1 != NULL)的判断避免错误; - 而且C标准明确规定,
free(NULL)是安全的,不会导致程序崩溃。
如果再次
free(str1)(已经置为NULL的情况)
完全没问题!标准C允许free(NULL),执行后不会有任何副作用,程序该干嘛干嘛。这也是我们要把释放后的指针置空的核心原因之一——避免重复释放的风险。如果
str2没置空,再次free(str2)会怎样?
这属于重复释放(double free),是C语言里典型的未定义行为。可能的结果包括:
- 直接触发程序崩溃;
- 悄悄破坏内存结构,导致后续程序在完全无关的地方出问题;
- 甚至看起来“正常运行”,但埋下了严重的隐患。
因为free后的内存已经被操作系统回收,再次释放会打乱内存管理器的正常工作,绝对要避免这种情况。
额外小提示
如果你想在函数里修改主函数里的指针本身(比如让原指针指向新分配的内存),那这两种写法都不够用了——你得传递指针的指针(也就是char **str),这时候数组形式的参数就不适用啦。
内容的提问来源于stack exchange,提问作者JuMoGar
相关产品推荐
相关产品推荐

