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
当前回答
至少对于gcc, __FILE__的值是编译器命令行中指定的文件路径。如果你像这样编译file.c:
gcc -c /full/path/to/file.c
__FILE__将展开为“/full/path/to/file.c”。如果你这样做:
cd /full/path/to
gcc -c file.c
那么__FILE__将展开为“file.c”。
这可能是实际的,也可能不是。
C标准不要求这种行为。关于__FILE__,它只是将其扩展为“当前源文件的假定名称(字符串字面值)”。
另一种方法是使用#line指令。它覆盖当前行号,也可选择覆盖源文件名。如果你想覆盖文件名但保留行号,使用__LINE__宏。
例如,你可以把它添加到文件的顶部。c:
#line __LINE__ "file.c"
唯一的问题是它将指定的行号赋给下一行,而#line的第一个参数必须是一个数字序列,因此您不能执行类似的操作
#line (__LINE__-1) "file.c" // This is invalid
确保#line指令中的文件名与文件的实际名称匹配作为练习。
至少对于gcc来说,这也会影响诊断消息中报告的文件名。
其他回答
如果您正在使用cmake,这里有一个提示。来自: http://public.kitware.com/pipermail/cmake/2013-January/053117.html
我在复制提示,所以都在这一页上:
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D__FILENAME__='\"$(subst
${CMAKE_SOURCE_DIR}/,,$(abspath $<))\"'")
如果您正在使用GNU make,我认为没有理由不能将其扩展到您自己的make文件。例如,你可能有这样的一行:
CXX_FLAGS+=-D__FILENAME__='\"$(subst $(SOURCE_PREFIX)/,,$(abspath $<))\"'"
其中$(SOURCE_PREFIX)是要删除的前缀。
然后使用__FILENAME__代替__FILE__。
下面是一个适用于Linux(路径'/')和Windows('\'和'/'混合)的可移植函数。使用gcc, clang和vs编译。
#include <string.h>
#include <stdio.h>
const char* GetFileName(const char *path)
{
const char *name = NULL, *tmp = NULL;
if (path && *path) {
name = strrchr(path, '/');
tmp = strrchr(path, '\\');
if (tmp) {
return name && name > tmp ? name + 1 : tmp + 1;
}
}
return name ? name + 1 : path;
}
int main() {
const char *name = NULL, *path = NULL;
path = __FILE__;
name = GetFileName(path);
printf("path: %s, filename: %s\n", path, name);
path ="/tmp/device.log";
name = GetFileName(path);
printf("path: %s, filename: %s\n", path, name);
path = "C:\\Downloads\\crisis.avi";
name = GetFileName(path);
printf("path: %s, filename: %s\n", path, name);
path = "C:\\Downloads/nda.pdf";
name = GetFileName(path);
printf("path: %s, filename: %s\n", path, name);
path = "C:/Downloads\\word.doc";
name = GetFileName(path);
printf("path: %s, filename: %s\n", path, name);
path = NULL;
name = GetFileName(NULL);
printf("path: %s, filename: %s\n", path, name);
path = "";
name = GetFileName("");
printf("path: %s, filename: %s\n", path, name);
return 0;
}
标准输出:
path: test.c, filename: test.c
path: /tmp/device.log, filename: device.log
path: C:\Downloads\crisis.avi, filename: crisis.avi
path: C:\Downloads/nda.pdf, filename: nda.pdf
path: C:/Downloads\word.doc, filename: word.doc
path: (null), filename: (null)
path: , filename:
只是希望改进一下FILE宏:
#定义文件(strrchr(__FILE__, '/') ?strrchr __FILE __, '/') + 1: strrchr __FILE __, '\\') ?strrchr(__FILE__, '\\') + 1: __FILE__)
这捕获/和\,像Czarek Tomczak要求的,这在我的混合环境中工作得很好。
这个解决方案是基于@RenatoUtsch的答案:
CMake列表:
string(LENGTH "${PROJECT_SOURCE_DIR}/" SOURCE_PATH_SIZE)
add_definitions("-DSOURCE_PATH_SIZE=${SOURCE_PATH_SIZE}")
add_definitions("-DSOURCE_PATH=\"${PROJECT_SOURCE_DIR}\"")
C / C + + header
#define __FILENAME__ strstr(__FILE__, SOURCE_PATH) + SOURCE_PATH_SIZE
一个简短的,适用于Windows和*nix的答案:
#define __FILENAME__ std::max<const char*>(__FILE__,\
std::max(strrchr(__FILE__, '\\')+1, strrchr(__FILE__, '/')+1))