C语言二维char数组指针传递后遍历异常,求技术解决
嘿,我完全懂你遇到的糟心事——你用二维字符数组存目录下的文件名,在主逻辑里用数组下标能正常打印,但把指针传给readFiles函数后,除了第一个文件名,后面全是乱码,甚至直接触发段错误,还没法通过移动指针来一次性打印整串。咱们来一步步拆解问题,找到靠谱的解决办法。
问题核心原因:指针类型不匹配
你犯了一个很容易踩的C语言坑:把二维字符数组的指针当成char**传递,但这两种指针根本不是一回事。
- 你的
char fileList[100][30]是二维数组,在内存里是连续存储的:每一行占30个char的空间,fileList[1]的地址是fileList[0] + 30,以此类推。 - 而
char**是指向char*的指针,它期望内存中存储的是一个个独立的char*地址(也就是每个字符串的首地址),但你的二维数组里存的是连续的字符,不是地址。
所以当你在readFiles里用*(allfiles + k)时:
- 对于k=0,刚好取到
fileList[0]的首地址,能正常打印; - 对于k≥1,程序会去
allfiles的地址加上k * sizeof(char*)的位置取一个值,把它当成字符串指针——但这个位置实际上是fileList[0]里的某个字符(比如64位系统下,sizeof(char*)是8,k=1时取的是fileList[0][8]开始的8个字节),这显然不是合法的内存地址,自然会读出乱码,甚至访问非法内存导致段错误。
两种可行的解决方案
方案一:用指向数组的指针传递二维数组(贴合原有代码)
这种方法不需要改变你原有的二维数组定义,只需要修改函数的参数类型:
- 修改
readFiles函数的参数类型
把原来的函数声明改成:
void readFiles( char (*allfiles)[30], int total_rows )
这里char (*allfiles)[30]表示一个指向长度为30的char数组的指针,正好匹配你二维数组fileList[100][30]的行指针类型。
- 调用函数时直接传递数组名
把原来的调用代码:
char **function_insert1 = &filename_reader; readFiles( function_insert1, filled_rows );
改成:
readFiles( fileList, filled_rows );
数组名fileList会自动退化为指向第一行的指针,也就是char (*)[30]类型,完美匹配函数参数。
- 函数内部逻辑无需修改
原来的打印代码printf( "%s\n", *( allfiles + k ) );可以正常工作,因为allfiles + k就是指向第k行的指针,解引用后就是第k行的字符串。
方案二:改用指针数组存储文件名(更灵活)
如果你更习惯用char**类型传递数据,可以把二维数组改成指针数组,每个元素指向一个独立的字符串:
- 修改数组定义
把char fileList[100][30];改成:
char *fileList[100];
- 存储文件名时分配独立内存
把原来的strcpy( fileList[filled_rows], in_file->d_name );改成:
fileList[filled_rows] = strdup(in_file->d_name); // 注意:strdup会自动分配内存,程序结束前要记得释放,避免内存泄漏
(如果你的环境不支持strdup,可以手动用malloc+strcpy实现:fileList[filled_rows] = malloc(strlen(in_file->d_name)+1); strcpy(fileList[filled_rows], in_file->d_name);)
- 调用函数时直接传递数组名
readFiles( fileList, filled_rows );
此时fileList是char**类型,和你原来的函数参数匹配,函数内部的*(allfiles +k)就是第k个文件名的指针,能正常打印。
- 释放内存避免泄漏
在程序结束前(比如closedir(dir)之后),添加循环释放每个字符串的内存:
for (int i = 0; i < filled_rows; i++) { free(fileList[i]); }
验证效果
用任意一种方案修改后,你再运行程序,readFiles函数就能通过移动指针正确打印所有文件名,不会再出现乱码和段错误了。
内容的提问来源于stack exchange,提问作者PluffTed

