C语言:函数外无法读取字符串数组,程序崩溃原因求助
问题解析:为什么
scanDir返回后主函数访问files会崩溃? 你碰到的这个问题本质是C语言里参数值传递的坑——哪怕你传的是char**,在scanDir里修改的也只是这个指针的副本,根本影响不到main函数里最初的files变量。
具体来捋一遍:
- 在main里你初始化了
char** files = 0;,调用scanDir(files, ...)的时候,函数的形参files是一个全新的变量,它只是复制了main中files的初始值(NULL)。 - 当你在
scanDir里执行files = malloc(...)或者files = realloc(...)时,你只是改变了这个形参files自己的指向,和main里的那个files半毛钱关系都没有。 - 等
scanDir执行完返回,main里的files还是最初的NULL,你接着去访问files[i],这不就是访问空指针嘛,程序不崩溃才怪。
怎么解决?有两种靠谱的方式:
方法一:用三级指针传参
把scanDir的参数改成char*** files,这样就能在函数内部直接修改main里files的指向:
#include <stdio.h> #include <dirent.h> #include <stdlib.h> #include <string.h> int scanDir(char*** files, char* path) { int size = 0, i = 0; DIR* dp = NULL; struct dirent* ep = NULL; *files = NULL; // 初始化外部指针为NULL dp = opendir(path); if (dp != NULL) { // 明确判断readdir的返回值是否为NULL,避免逻辑隐患 while ((ep = readdir(dp)) != NULL) { // 重新分配内存,修改的是main中files的实际指向 *files = realloc(*files, sizeof(char*) * (size + 1)); (*files)[i] = malloc(sizeof(char) * (strlen(ep->d_name) + 1)); strcpy((*files)[i], ep->d_name); size++; i++; } closedir(dp); } return size; } int main(void) { char** files = NULL; int size = 0, i = 0; // 传files的地址给scanDir size = scanDir(&files, "C:\\Users\\user\\test"); for (i = 0; i < size; i++) { puts(files[i]); free(files[i]); } free(files); getchar(); return 0; }
方法二:让函数直接返回分配好的char**
这种写法更直观,把分配好的指针直接返回给main函数,同时用指针参数带回文件数量:
#include <stdio.h> #include <dirent.h> #include <stdlib.h> #include <string.h> char** scanDir(char* path, int* size) { char** files = NULL; int i = 0; DIR* dp = NULL; struct dirent* ep = NULL; *size = 0; dp = opendir(path); if (dp != NULL) { while ((ep = readdir(dp)) != NULL) { files = realloc(files, sizeof(char*) * (*size + 1)); files[i] = malloc(sizeof(char) * (strlen(ep->d_name) + 1)); strcpy(files[i], ep->d_name); (*size)++; i++; } closedir(dp); } return files; } int main(void) { char** files = NULL; int size = 0, i = 0; // 直接接收返回的指针,同时传入size的地址获取文件数量 files = scanDir("C:\\Users\\user\\test", &size); for (i = 0; i < size; i++) { puts(files[i]); free(files[i]); } free(files); getchar(); return 0; }
最后提个小细节:
原来的代码里while (ep = readdir(dp))最好改成while ((ep = readdir(dp)) != NULL),虽然在大多数情况下前者也能工作,但后者更严谨,能明确判断目录读取结束的条件。
内容的提问来源于stack exchange,提问作者Daniel.
相关产品推荐
相关产品推荐

