如果我想分配一个 char 数组(在 C 中),它保证足够大以容纳任何有效的绝对路径+文件名,它需要多大。
在 Win32 上,有 MAX_PATH 定义。Unix/linux 的等价物是什么?
有一个PATH_MAX
,但它有点问题。从realpath(3)手册页的 bugs 部分:
此函数的 POSIX.1-2001 标准版本被设计破坏,因为无法确定输出缓冲区的合适大小resolve_path。根据 POSIX.1-2001,大小为PATH_MAX的缓冲区就足够了,但PATH_MAX不必是定义的常量,可能必须使用pathconf(3)获得。并且询问pathconf(3)并没有真正的帮助,因为一方面 POSIX 警告pathconf(3)的结果可能很大并且不适合分配内存,另一方面 pathconf(3)可能会返回 -1 到表示PATH_MAX 不受限制。
到目前为止,关于 *nix 方面的其他答案似乎都是正确的,但我会在 Windows 上添加一个关于它的警告。
您被文档欺骗(通过遗漏)。
MAX_PATH
确实已定义,甚至可能适用于存储在 FAT 或 FAT32 上的文件。但是,任何路径名都可以加上前缀\\?\
来告诉 Windows API 忽略MAX_PATH
并让文件系统驱动程序自己决定。在那之后,定义变得模糊。
再加上路径名称实际上是 Unicode(嗯,UTS-16)的事实,并且当使用“ANSI”API 时,与内部 Unicode 名称之间的转换取决于一系列因素,包括当前代码页,你有一个混乱的秘诀。
MSDN上对 Windows 的规则进行了很好的描述。规则比我在这里总结的要复杂得多。
编辑:感谢 KitsuneYMG 的评论,我改成\\.\
了上面的。\\?\
Windows 路径和命名空间很复杂。有些人甚至可能认为它们太复杂了。复杂性的一个来源是 Win32(现在是 Win64)API 是一个位于 Windows NT 本地系统之上的子系统。
没有任何前缀的路径在最广泛的 Windows 平台上兼容。如果它仅限于 7 位 ASCII 字符,那么它与 2.0 版左右的 16 位 DOS 兼容(无论何时引入子目录,实际上可能已经在 DOS 3 中;但 DOS 1.0 只有根目录和\
字符没有特殊意义)。
前缀导致路径名的\\?\
平衡被逐字传递给适当的文件系统驱动程序,这产生了删除对MAX_PATH
字符的限制的效果。如果长路径名也在网络共享上,那么您可以使用带有前缀的扩展 UNC 名称,\\?\UNC\server\share\
而不是普通的 UNC 名称\\server\share\
。使用此前缀会限制对 Win32 和更高版本的 Windows 平台的可移植性,但除非您需要在旧硬件上支持 16 位 Windows,否则这不是一个大问题。
\\.\
前缀是另一种动物。它允许访问一组特殊命名的设备之外的设备对象,这些设备由 Windows 作为特殊文件名自动映射到每个文件夹中。这些特殊名称包括 CON、PRN、AUX、NUL、COM1、COM2、COM3、COM4、COM5、COM6、COM7、COM8、COM9、LPT1、LPT2、LPT3、LPT4、LPT5、LPT6、LPT7、LPT8 和 LPT9。请注意,所有这些名称都是特殊的,无论是否使用扩展名,或者大小写混合。但您可能安装了 10 个或更多 COM 端口。如果您使用 USB 调制解调器或 USB 串行端口适配器,这种情况很快就会发生,因为每个唯一的基于 USB 的串行端口都将被分配一个不同的 COMn 名称。如果需要访问第 50 个串口,那么只能使用名称\\.\COM50
,因为 COM50不是像 COM1 这样的特殊名称。
我上面引用的 MSDN 页面有区别,我只是在原始答案中输入了不正确的前缀。
好吧,至少在 Linux 上,有:
PATH_MAX
(定义在limits.h
)
FILENAME_MAX
(定义在stdio.h
)
这两个都设置4096
在我的系统(x86 Linux)上。
更新::来自glibc 手册的一些信息
仅当系统对相关参数具有固定、统一的限制时,才会在 limits.h 中定义以下每个宏。如果系统允许不同的文件系统或文件有不同的限制,那么宏是未定义的;使用 pathconf 或 fpathconf 找出适用于特定文件的限制
FILENAME_MAX 是 ISO C 标准的一部分,它适用于 UNIX 和 Windows。但是,GNU C 库文档包含以下警告:
“与 PATH_MAX 不同,即使没有施加实际限制,也会定义此宏。在这种情况下,它的值通常是一个非常大的数字。在 GNU 系统上总是如此。
使用说明:不要使用 FILENAME_MAX 作为存储文件名的数组的大小!你不可能做一个那么大的数组!使用动态分配。”
您可以pathconf()
在运行时使用它来计算,但在<limits.h>
.
您可以使用该realpath
函数为特定路径分配足够大的缓冲区。如果您将空指针作为第二个参数传递给它,它将为路径分配一个足够大的缓冲区。手册页可能比我能更好地解释它:
realpath() 扩展所有符号链接并解析对 /./、/../ 和由 path 命名的以 null 结尾的字符串中的额外“/”字符的引用,以生成规范化的绝对路径名。生成的路径名存储为以 null 结尾的字符串,最多 PATH_MAX 个字节,存储在 resolved_path 指向的缓冲区中。生成的路径将没有符号链接、/./ 或 /../ 组件。
如果将 resolved_path 指定为 NULL,则 realpath() 使用 malloc(3) 分配一个最多 PATH_MAX 字节的缓冲区来保存已解析的路径名,并返回指向此缓冲区的指针。调用者应该使用 free(3) 释放这个缓冲区。
限制.h
/*
* File system limits
*
* NOTE: Apparently the actual size of PATH_MAX is 260, but a space is
* required for the NUL. TODO: Test?
* NOTE: PATH_MAX is the POSIX equivalent for Microsoft's MAX_PATH; the two
* are semantically identical, with a limit of 259 characters for the
* path name, plus one for a terminating NUL, for a total of 260.
*/
#define PATH_MAX 260
minwindef.h
#define MAX_PATH 260