C语言自定义file_name函数提取Windows路径文件名无输出问题排查
代码无法正常运行的核心原因
你的代码存在多个严重的未定义行为,直接导致运行异常:
- 数组下标非法越界:你初始化
i = -1,直接访问addr[i]等价于访问字符串首地址之前的未知内存,完全没有读取到路径的末尾字符。C语言字符串的下标从0开始,要从末尾遍历首先需要调用strlen获取字符串总长度,从下标长度-1的位置开始倒序遍历。 - 循环无边界保护:如果传入的路径没有反斜杠,循环会一直向低地址越界读取内存,直到碰巧读到值为
'\\'的字节,或者触发内存访问错误导致程序崩溃,这就是你遇到卡顿后退出的核心原因。 - 字符串缺少结束标记:你向
name数组写入完文件名后没有追加'\0'结束符,C语言的字符串依赖'\0'判断结束,后续printf读取时会越界访问name数组之外的内存,输出乱码或者触发异常。 - 反转逻辑错误:反转数组的循环条件写为
count < len,会导致每个字符被交换两次,最终回到倒序状态,正确的反转应该只遍历前半段,条件为count < len / 2。
static修饰局部变量的原理
C语言的变量根据存储位置分为三类:
- 栈区变量:默认的局部变量都存在栈区,函数调用结束后栈帧会被回收,对应的变量内存会被后续操作覆盖,直接返回栈区变量的地址是非法操作,访问时会出现未定义行为。
- 静态存储区变量:被
static修饰的局部变量会被放到静态存储区,整个程序运行周期内这块内存都不会被释放,地址持续有效,所以返回它的指针是合法的。但注意静态变量是全局共享的,多次调用函数会覆盖之前存储的内容,不支持多线程安全使用。 - 堆区变量:通过
malloc动态申请的内存存在堆区,需要手动调用free释放,生命周期由开发者控制。
C标准库的现成路径处理函数
C标准本身没有规定专门的文件名提取函数,但不同平台有成熟的实现:
- Windows平台MSVC/MinGW都支持
_splitpath函数,可以直接拆分路径的盘符、目录、文件名、后缀四个部分。 - 符合POSIX标准的环境(包括Windows下的GCC)可以通过包含
<libgen.h>头文件,调用basename()函数,直接传入路径字符串即可返回文件名部分的指针。
修正后的参考实现
#include <string.h> char* file_name(char* addr) { static char name[100]; int len = strlen(addr); int i = len - 1; int name_len = 0; // 从末尾找第一个反斜杠 while (i >= 0 && addr[i] != '\\') { i--; } // 拷贝文件名,i+1就是文件名的起始下标 name_len = len - (i + 1); if (name_len >= 100) name_len = 99; // 防止数组越界 strncpy(name, addr + i + 1, name_len); name[name_len] = '\0'; // 追加字符串结束符 return name; }
内容的提问来源于stack exchange,提问作者Anuj Jodha
相关产品推荐
相关产品推荐

