遍历字符数组时为何每次偏移1字节而非获取下一个数组元素?
嘿,我来帮你排查这个头疼的问题!你遇到的字符串截断现象,根源是代码里的几个基础语法和逻辑错误,咱们一步步拆解清楚:
1. 指针数组声明错误
你在main里写的这句:
char *file = {"file1.txt", "file2.txt", "file3.txt"};
是完全错误的声明方式。你想定义的是一个存储字符串指针的数组,但这里少了[],导致file被当成单个char*指针,而非指针数组。编译器处理这种非法初始化时,只会把第一个字符串"file1.txt"的地址赋值给file,后面的字符串会被直接忽略,内存布局完全不符合你的预期——这也是后续偏移错误的核心原因。
正确的声明应该是:
char *file[] = {"file1.txt", "file2.txt", "file3.txt"};
2. 文件个数计算错误
接下来这句计算文件数量的代码:
int numberOfFiles = sizeof(file);
如果file是指针数组,sizeof(file)得到的是数组的总字节数(比如64位系统下,每个指针占8字节,3个元素就是24字节),而不是你想要的元素个数。正确的计算方式是用总字节数除以单个元素的字节数:
int numberOfFiles = sizeof(file) / sizeof(file[0]);
3. 函数传参错误
你调用GetFileContent时传的是&file[i],但file[i]本身就是指向目标字符串的char*指针,&file[i]是char**类型(指针的指针)。当你把char**传给期望char*的参数时,编译器会做隐式转换,把指针的内存地址当成字符串的起始地址。
在你原来错误的声明下,file是单个指针,指向"file1.txt"的首地址,&file[i]等价于(char*)((char*)file + i)——也就是从"file1.txt"的首地址偏移i个字节,所以i=1时就指向了字符串的第二个字符'i',自然读出"ile1.txt",i=2时偏移2字节,读出"le1.txt",完全匹配你遇到的问题!
正确的传参应该直接传file[i]:
tmpStruct.entireFile = GetFileContent(file[i]);
补充:GetFileContent的健壮性优化
你的GetFileContent函数没有检查文件打开和内存分配是否成功,如果文件不存在、权限不足或者内存耗尽,程序会直接崩溃。建议加上错误处理:
char *GetFileContent(char *filePath) { char *buffer = NULL; size_t size = 0; FILE *file = fopen(filePath, "r"); if (!file) { // 检查文件是否打开成功 perror("Failed to open file"); return NULL; } fseek(file, 0, SEEK_END); size = ftell(file); rewind(file); buffer = malloc((size + 1) * sizeof(*buffer)); if (!buffer) { // 检查内存分配是否成功 perror("Failed to allocate memory"); fclose(file); return NULL; } fread(buffer, size, 1, file); fclose(file); buffer[size] = '\0'; return buffer; }
修正后的完整代码
#include <stdio.h> #include <stdlib.h> #include <string.h> // 补充结构体定义(假设你原来的结构体是这样) struct ArrayStoredInHeap { char *entireFile; }; char *GetFileContent(char *filePath) { char *buffer = NULL; size_t size = 0; FILE *file = fopen(filePath, "r"); if (!file) { perror("Failed to open file"); return NULL; } fseek(file, 0, SEEK_END); size = ftell(file); rewind(file); buffer = malloc((size + 1) * sizeof(*buffer)); if (!buffer) { perror("Failed to allocate memory"); fclose(file); return NULL; } fread(buffer, size, 1, file); fclose(file); buffer[size] = '\0'; return buffer; } int main (void) { char *file[] = {"file1.txt", "file2.txt", "file3.txt"}; int numberOfFiles = sizeof(file) / sizeof(file[0]); struct ArrayStoredInHeap myStruct[numberOfFiles]; for(int i = 0; i < numberOfFiles; i++) { struct ArrayStoredInHeap tmpStruct; tmpStruct.entireFile = GetFileContent(file[i]); myStruct[i] = tmpStruct; } for(int i = 0; i < numberOfFiles; i++) { if (myStruct[i].entireFile) { printf("%s \n", myStruct[i].entireFile); free(myStruct[i].entireFile); // 别忘了释放内存,避免泄漏 } getchar(); } return 0; }
另外,别忘了最后释放GetFileContent分配的内存,避免内存泄漏哦!
内容的提问来源于stack exchange,提问作者praiseHellRaiseDale

