如何在另一个函数中修改char**?C语言字符串数组赋值错误排查
问题分析与修复方案
错误根源
你的代码里,func函数循环内的char buf[10];是栈上的局部变量。整个for循环中,buf复用的是同一块栈内存地址——每次循环调用snprintf都会把新内容写入这块内存,然后将该地址赋值给s[i]。当func执行完毕返回main时,栈上的buf内存会被操作系统回收,此时s数组的三个指针都指向同一块已经失效的内存区域。而这块内存最后一次被写入的内容是#2,所以main中打印时三个指针输出的都是这个值。
修复方案
以下是两种实用的修复方式:
方式1:动态分配堆内存
通过malloc在堆上分配内存,堆内存不会随函数返回而释放,注意使用完后要手动释放避免内存泄漏:
#include <stdio.h> #include <stdlib.h> void func(char **s){ for(int i=0; i<3; i++){ char *buf = malloc(10); if (!buf) { // 检查内存分配是否成功 perror("malloc failed"); exit(EXIT_FAILURE); } snprintf(buf, 10, "#%d", i); s[i] = buf; } } int main() { char *s[3]; func(s); for(int i=0; i<3; i++){ printf("%s ", s[i]); } // 释放堆内存 for(int i=0; i<3; i++){ free(s[i]); } return 0; }
方式2:预先分配栈缓冲区
在main中提前分配好足够的缓冲区,传递给func使用,缓冲区的生命周期覆盖整个打印过程:
#include <stdio.h> void func(char **s, char bufs[3][10]){ for(int i=0; i<3; i++){ snprintf(bufs[i], 10, "#%d", i); s[i] = bufs[i]; } } int main() { char *s[3]; char bufs[3][10]; // 预先分配3个长度为10的栈缓冲区 func(s, bufs); for(int i=0; i<3; i++){ printf("%s ", s[i]); } return 0; }
补充:静态缓冲区方案(谨慎使用)
如果不想用动态分配或提前传缓冲区,可以使用静态存储区的缓冲区数组,但静态内存是全局共享的,多次调用func会覆盖之前的数据,仅适合一次性场景:
#include <stdio.h> void func(char **s){ static char bufs[3][10]; for(int i=0; i<3; i++){ snprintf(bufs[i], 10, "#%d", i); s[i] = bufs[i]; } } int main() { char *s[3]; func(s); for(int i=0; i<3; i++){ printf("%s ", s[i]); } return 0; }
内容的提问来源于stack exchange,提问作者Unyaya
相关产品推荐
相关产品推荐

