C语言中可用的标准预定义宏__FILE__显示文件的完整路径。有办法缩短这条路吗?我的意思是
/full/path/to/file.c
我看到
to/file.c
or
file.c
C语言中可用的标准预定义宏__FILE__显示文件的完整路径。有办法缩短这条路吗?我的意思是
/full/path/to/file.c
我看到
to/file.c
or
file.c
当前回答
I think this is better than using strrchr function. strfnchr will search last delemeter '/' and get filename from __FILE__ and you can use __FILE__NAME__ instead __FILE__ for get file name without full file path. strrchr solution searching filename twice per use. but this code is just 1 time search. And it works effectively even if there is no seperater '/' in __FILE__. You can use it by replacing it with \ as needed. The source code of strfnchr was improved by using the source code of strrchr below. I think it will work more effectively than strrchr. https://code.woboq.org/userspace/glibc/string/strrchr.c.html
inline const char* strfnchr(const char* s, int c) {
const char* found = s;
while (*(s++)) {
if (*s == c)
found = s;
}
if (found != s)
return found + 1;
return s;
}
#define __FILE_NAME__ strfnchr(__FILE__, '/')
其他回答
如果你使用CMAKE和GNU编译器,这个全局定义工作正常:
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D__MY_FILE__='\"$(notdir $(abspath $<))\"'")
我多年来一直使用@Patrick的答案。
当完整路径包含符号链接时,它有一个小问题。
更好的解决方案。
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-builtin-macro-redefined -D'__FILE__=\"$(subst $(realpath ${CMAKE_SOURCE_DIR})/,,$(abspath $<))\"'")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-builtin-macro-redefined -D'__FILE__=\"$(subst $(realpath ${CMAKE_SOURCE_DIR})/,,$(abspath $<))\"'")
为什么要用这个?
-Wno-builtin-macro-redefined to mute the compiler warnings for redefining __FILE__ macro. For those compilers do not support this, refer to the Robust way below. Strip the project path from the file path is your real requirement. You won't like to waste the time to find out where is a header.h file, src/foo/header.h or src/bar/header.h. We should strip the __FILE__ macro in cmake config file. This macro is used in most exists codes. Simply redefine it can set you free. Compilers like gcc predefines this macro from the command line arguments. And the full path is written in makefiles generated by cmake. Hard code in CMAKE_*_FLAGS is required. There is some commands to add compiler options or definitions in some more recently version, like add_definitions() and add_compile_definitions(). These commands will parse the make functions like subst before apply to source files. That is not we want.
重新定义- wno -内置宏的健壮方法。
include(CheckCCompilerFlag)
check_c_compiler_flag(-Wno-builtin-macro-redefined SUPPORT_C_WNO_BUILTIN_MACRO_REDEFINED)
if (SUPPORT_C_WNO_BUILTIN_MACRO_REDEFINED)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-builtin-macro-redefined")
endif (SUPPORT_C_WNO_BUILTIN_MACRO_REDEFINED)
include(CheckCXXCompilerFlag)
check_cxx_compiler_flag(-Wno-builtin-macro-redefined SUPPORT_CXX_WNO_BUILTIN_MACRO_REDEFINED)
if (SUPPORT_CXX_WNO_BUILTIN_MACRO_REDEFINED)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-builtin-macro-redefined")
endif (SUPPORT_CXX_WNO_BUILTIN_MACRO_REDEFINED)
记住从集合(*_FLAGS…-D__FILE__ =…)。
我刚刚想到了一个很好的解决方案,它可以同时使用源文件和头文件,非常有效,并且可以在所有平台的编译时工作,没有特定于编译器的扩展。此解决方案还保留了项目的相对目录结构,因此您可以知道文件在哪个文件夹中,并且只相对于项目的根目录。
其思想是用构建工具获取源目录的大小,并将其添加到__FILE__宏中,完全删除目录,只显示从源目录开始的文件名。
下面的例子是使用CMake实现的,但是没有理由它不能与任何其他构建工具一起工作,因为技巧非常简单。
在CMakeLists.txt文件中,定义一个宏,该宏具有到CMake上项目的路径长度:
# The additional / is important to remove the last character from the path.
# Note that it does not matter if the OS uses / or \, because we are only
# saving the path size.
string(LENGTH "${CMAKE_SOURCE_DIR}/" SOURCE_PATH_SIZE)
add_definitions("-DSOURCE_PATH_SIZE=${SOURCE_PATH_SIZE}")
在你的源代码中,定义一个__FILENAME__宏,它只是将源路径大小添加到__FILE__宏:
#define __FILENAME__ (__FILE__ + SOURCE_PATH_SIZE)
然后使用这个新宏而不是__FILE__宏。这是因为__FILE__路径总是以CMake源目录的路径开始。通过从__FILE__字符串中移除它,预处理器将负责指定正确的文件名,并且它都将相对于你的CMake项目的根。
如果你关心性能,这与使用__FILE__一样有效,因为__FILE__和SOURCE_PATH_SIZE都是已知的编译时常量,因此可以由编译器优化。
唯一会失败的地方是如果你在生成的文件上使用这个,而且它们在一个off-source build文件夹上。然后,您可能必须使用CMAKE_BUILD_DIR变量而不是CMAKE_SOURCE_DIR创建另一个宏。
因为使用的是GCC,所以可以利用
__BASE_FILE__这个宏扩展为主输入文件的名称,以C字符串常量的形式。这是源文件 在预处理器或C编译器的命令行中指定
然后在编译时通过更改源文件表示(完整路径/相对路径/basename)来控制显示文件名的方式。
编译时没有办法做到这一点。显然,您可以在运行时使用C运行时实现它,正如其他一些答案所演示的那样,但是在编译时,当预处理器启动时,您就不走运了。