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
当前回答
c++ 11 msvc2015u3、gcc5.4 clang3.8.0 模板<typename T, size_t S> (const T (& str)[S], size_t i = S - 1) { 返回(str[i] == '/' || str[i] == '\\') ?I + 1:(I > 0 ?Get_file_name_offset (str, I - 1): 0); } template <typename T> (T (& str)[1]) { 返回0; }
'
int main()
{
printf("%s\n", &__FILE__[get_file_name_offset(__FILE__)]);
}
代码在以下情况下产生编译时偏移量:
gcc:至少gcc6.1 + -O1 Msvc:将结果放入constexpr变量: constexpr auto file = &__FILE__[get_file_name_offset(__FILE__)]; printf (" % s \ n ",文件); Clang:坚持不编译时计算
有一个技巧可以强制所有3个编译器进行编译时间计算,即使在调试配置中禁用优化:
namespace utility {
template <typename T, T v>
struct const_expr_value
{
static constexpr const T value = v;
};
}
#define UTILITY_CONST_EXPR_VALUE(exp) ::utility::const_expr_value<decltype(exp), exp>::value
int main()
{
printf("%s\n", &__FILE__[UTILITY_CONST_EXPR_VALUE(get_file_name_offset(__FILE__))]);
}
https://godbolt.org/z/u6s8j3
其他回答
只是希望改进一下FILE宏:
#定义文件(strrchr(__FILE__, '/') ?strrchr __FILE __, '/') + 1: strrchr __FILE __, '\\') ?strrchr(__FILE__, '\\') + 1: __FILE__)
这捕获/和\,像Czarek Tomczak要求的,这在我的混合环境中工作得很好。
因为使用的是GCC,所以可以利用
__BASE_FILE__这个宏扩展为主输入文件的名称,以C字符串常量的形式。这是源文件 在预处理器或C编译器的命令行中指定
然后在编译时通过更改源文件表示(完整路径/相对路径/basename)来控制显示文件名的方式。
我多年来一直使用@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__ =…)。
纯粹的编译时解决方案。它基于这样一个事实:字符串字面量的sizeof()返回其长度+1。
#define STRIPPATH(s)\
(sizeof(s) > 2 && (s)[sizeof(s)-2] == '/' ? (s) + sizeof(s) - 1 : \
sizeof(s) > 3 && (s)[sizeof(s)-3] == '/' ? (s) + sizeof(s) - 2 : \
sizeof(s) > 4 && (s)[sizeof(s)-4] == '/' ? (s) + sizeof(s) - 3 : \
sizeof(s) > 5 && (s)[sizeof(s)-5] == '/' ? (s) + sizeof(s) - 4 : \
sizeof(s) > 6 && (s)[sizeof(s)-6] == '/' ? (s) + sizeof(s) - 5 : \
sizeof(s) > 7 && (s)[sizeof(s)-7] == '/' ? (s) + sizeof(s) - 6 : \
sizeof(s) > 8 && (s)[sizeof(s)-8] == '/' ? (s) + sizeof(s) - 7 : \
sizeof(s) > 9 && (s)[sizeof(s)-9] == '/' ? (s) + sizeof(s) - 8 : \
sizeof(s) > 10 && (s)[sizeof(s)-10] == '/' ? (s) + sizeof(s) - 9 : \
sizeof(s) > 11 && (s)[sizeof(s)-11] == '/' ? (s) + sizeof(s) - 10 : (s))
#define __JUSTFILE__ STRIPPATH(__FILE__)
请随意将条件操作符级联扩展到项目中最大的合理文件名。路径长度并不重要,只要检查距离字符串的末尾足够远。
我将看看我是否可以得到一个类似的宏,没有硬编码的长度与宏递归…
c++ 11 msvc2015u3、gcc5.4 clang3.8.0 模板<typename T, size_t S> (const T (& str)[S], size_t i = S - 1) { 返回(str[i] == '/' || str[i] == '\\') ?I + 1:(I > 0 ?Get_file_name_offset (str, I - 1): 0); } template <typename T> (T (& str)[1]) { 返回0; }
'
int main()
{
printf("%s\n", &__FILE__[get_file_name_offset(__FILE__)]);
}
代码在以下情况下产生编译时偏移量:
gcc:至少gcc6.1 + -O1 Msvc:将结果放入constexpr变量: constexpr auto file = &__FILE__[get_file_name_offset(__FILE__)]; printf (" % s \ n ",文件); Clang:坚持不编译时计算
有一个技巧可以强制所有3个编译器进行编译时间计算,即使在调试配置中禁用优化:
namespace utility {
template <typename T, T v>
struct const_expr_value
{
static constexpr const T value = v;
};
}
#define UTILITY_CONST_EXPR_VALUE(exp) ::utility::const_expr_value<decltype(exp), exp>::value
int main()
{
printf("%s\n", &__FILE__[UTILITY_CONST_EXPR_VALUE(get_file_name_offset(__FILE__))]);
}
https://godbolt.org/z/u6s8j3