网络彩票网站建设,温州快速建站公司,网站网址查询 优帮云,电商22个货源网址目录标题C/C获取文件名的方法__FILE__宏避免__FILE__宏的错误慎用$(subst $(dir $),,$)\)来重定义__BASE_FILE__宏__builtin_FILE()函数Windows API函数GetModuleFileName()getenv()使用cmake中的变量重定义__FILE__宏的CMake示例C/C获取文件名的方法 使用…
目录标题C/C获取文件名的方法__FILE__宏避免__FILE__宏的错误慎用$(subst $(dir $),,$)\)来重定义__BASE_FILE__宏__builtin_FILE()函数Windows API函数GetModuleFileName()getenv()使用cmake中的变量重定义__FILE__宏的CMake示例C/C获取文件名的方法 使用__FILE__宏 可以获取当前源码文件的文件名 使用__builtin_FILE()函数 __builtin_FILE()是一个内建函数,不同于__FILE__是一个预定义宏因此__builtin_FILE()的效率可能更高。 使用__BASE_FILE__宏 与__FILE__宏和__builtin_FILE()函数功能类似,它只包含当前编译单元的文件名不包含任何路径信息理论上是这样实际往往跟__FILE__内容一致。 使用__PRETTY_FUNCTION__宏 __func__宏可以获取当前函数名而__PRETTY_FUNCTION__宏可以获取当前函数的带有参数和返回类型的完整签名其中包含了源码文件路径。 使用标准库中的getenv函数获取pwd路径 pwd 大家都懂。 Windows API函数GetModuleFileName() 使用Windows API函数GetModuleFileName()可以获取当前程序的完整路径 编译时譬如在cmake中获取文件名并声明宏 编译时必然要获取所有源文件这时候用这些文件名定义一个宏即可。 __FILE__宏 近年来C/C标准中的__FILE__宏定义引起了广泛关注。该宏定义可用于获取当前程序的文件路径但是它也有一些限制和风险。 首先让我们来看看__FILE__宏定义的定义和用法。__FILE__宏定义的作用是返回当前源文件的名称这个名称可以在命令行或环境变量中设置。例如假设你在C语言中编写了一个文件读取函数readFile并且在代码中定义了myfile.c作为目标文件名那么你可以使用以下代码获取当前文件的名称 #include stdio.h int main() { printf(Current file name: %s\n, __FILE__); return 0;
} 然而由于该宏定义只能返回当前源文件的名称因此在某些情况下可能会导致问题。例如如果你正在使用共享库或第三方库而这些库或库中使用了与原始文件不同的文件名那么__FILE__宏定义就无法正确地获取到库或库中使用的文件名。此外即使在单线程环境下__FILE__宏定义也不是一个安全的选项因为它允许攻击者获取到当前程序的完整文件名。 因此虽然__FILE__宏定义非常有用但我们需要考虑它的安全性和限制。在实际应用中我们可以通过使用更加安全的文件操作函数来替换__FILE__宏定义。例如在Windows系统中你可以使用资源管理器来读取和写入文件而不需要使用预处理器指令。在Linux系统中你可以使用进程空间的文件访问权限来达到类似的效果。 接下来让我们分析一下__FILE__宏定义存在的风险和限制。首先__FILE__宏定义只能返回当前源文件的名称因此在某些情况下可能会导致问题。例如如果你正在使用共享库或第三方库而这些库或库中使用了与原始文件不同的文件名那么__FILE__宏定义就无法正确地获取到库或库中使用的文件名。此外即使在单线程环境下__FILE__宏定义也不是一个安全的选项因为它允许攻击者获取到当前程序的完整文件名。 其次__FILE__宏定义还有一些局限性它并不能正确地返回当前程序的真正文件路径。事实上计算机文件系统的逻辑结构是非常复杂的它由多个层次组成。例如根目录下的子目录结构、父目录结构等都会影响到文件的真正路径。因此__FILE__宏定义并不能准确地反映出文件的路径。 避免__FILE__宏的错误 FILE 宏返回的是绝对路径的名称但是在很多时候我们只需要获取文件名即可,而不需要那一长段繁琐的目录前缀,这时候我们需要对__FILE__宏重定义,当然这只是在不得不用__FILE__宏的情况,如果不是这样,你完全可以用其他方式。。 避免__FILE__宏被重定向到错误的文件我们可以按照以下建议进行操作 如果使用的是CMake 3.14及以上版本可以使用CMAKE_CURRENT_LIST_FILE变量来获取当前正在处理的CMake列表文件的完整路径而不是使用__FILE__宏。 如果您的项目中使用了多个CMake文件可以在每个文件中使用不同的宏定义来避免重复定义__FILE__宏。需要仔细检查您的代码和CMake文件并确保它们是正确的并使用适当的宏定义和变量来获取文件路径。 慎用$(subst $(dir $),,$)\)来重定义 这个语法是GNU make中的函数subst的使用用于将字符串中的某个子串替换为另一个字符串。 在 Makefile 中$ 表示当前规则中的第一个依赖文件$(dir $) 表示 $ 的目录部分$(subst OLD,NEW,TEXT) 表示将 TEXT 中的 OLD 字符串替换为 NEW 字符串。 因此$(subst $(dir ),,),,),,) 表示将 $ 中的目录部分替换为空即只保留文件名部分。 例如如果当前规则中的第一个依赖文件是 src/foo/bar.c那么$(dir $)的值为 src/foo/$(subst $(dir $),,$) 的值就是 bar.c。然后“”) 表示在文件名后添加一个双引号和单引号以便将文件名传递给编译器。 在cmake工程中set(CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} -U__FILE__ -D__FILE__\$(subst $(dir $),,$)\)这个命令告诉编译器不要定义__FILE__宏而是在后面使用-D__FILE__“$(subst $(dir ),,),,),,)”选项重新定义__FILE__宏将其重定向到输入文件的相对路径。 依赖文件名并不一定意味着源文件名有时候会被指定为编译器依赖项文件名。 这时候我们的__FILE__就会得不到正确的文件名而且重定向到错误的中间文件名上比如compiler_depend.ts文件有关此文件的介绍可以查看Cmake 中 compiler_depend.ts文件 __BASE_FILE__宏 如果您使用的是GCC编译器可以使用__BASE_FILE__宏来获取当前源文件的路径而不是使用__FILE__宏。该宏在GCC 4.3及以上版本中可用。 __BASE_FILE__宏包含文件名但不包含文件路径。但是如果你在源代码中包含了文件路径那么__BASE_FILE__宏的值将包含路径。这是由于__BASE_FILE__宏的值是在预处理阶段计算的此时源代码中包含的文件路径已经被展开了。 例如假设你的源代码文件位于/path/to/source目录下且包含以下行 #include file.h 在预处理阶段这行代码将被展开为 #include /path/to/source/file.h 因此在这种情况下__BASE_FILE__宏的值将是file.h但包含路径/path/to/source。 __builtin_FILE()函数 __builtin_FILE()函数确实是GCC内置函数之一但是其具体实现并不是源代码形式的而是由GCC编译器自带的。因此我们无法提供其具体源代码的定义。__builtin_FILE()函数的实现方式可能随着GCC版本的更新而发生变化因此无法确切地给出其源代码的定义。 __builtin_FILE()函数的作用是获取当前文件的文件名它是由编译器自动实现的。在使用该函数时只需要在代码中调用__builtin_FILE()函数即可无需手动编写该函数的源代码。由于是内建函数可以被编译器优化理论上比__FILE__宏效率更高。 重定义时要指定参数set(CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} -fno-builtin) Windows API函数GetModuleFileName() GetModuleFileName()是Windows API函数之一用于获取指定模块的文件名包括路径和文件名。该函数提供了一种方法可以在运行时获取当前可执行文件的路径和文件名。 DWORD GetModuleFileName(HMODULE hModule,LPSTR lpFilename,DWORD nSize
);其中hModule参数指定要获取路径和文件名的模块的句柄。如果该参数为NULL则GetModuleFileName()函数将返回调用它的可执行文件的路径和文件名。 lpFilename参数是指向一个缓冲区的指针用于接收路径和文件名。该缓冲区必须足够大以至于可以容纳完整的路径和文件名。如果函数成功执行lpFilename将包含路径和文件名。 nSize参数指定缓冲区的大小以字节为单位。如果lpFilename缓冲区的大小小于路径和文件名的长度函数将无法成功执行并返回0。 GetModuleFileName()函数返回值表示复制到缓冲区的字符数不包括结尾的空字符。如果函数执行失败返回值为0。 使用GetModuleFileName()函数我们可以在运行时获取当前可执行文件的路径和文件名并将其存储到缓冲区中。例如 #include windows.h#include stdio.hint main() {char path[MAX_PATH];GetModuleFileName(NULL, path, MAX_PATH);printf(The current file is: %s\n, path);return 0;}getenv() 使用getenv函数即可没必要使用system之类执行shell命令的函数。 getenv() 函数的返回值是一个指向环境变量值的字符串指针可以将其用于后续的操作例如打印、比较等等。而 system() 函数的返回值是执行命令的状态码用于判断命令是否执行成功。 getenv() 函数在获取环境变量时不会对系统进行任何修改只是返回变量的值。而 system() 函数会执行指定的系统命令可能会对系统进行修改例如创建、删除文件等等。 #include iostream
#include cstdlibint main() {const char* filename std::getenv(PWD); //获取当前工作目录std::cout filename std::endl;return 0;
} 使用cmake中的变量重定义__FILE__宏的CMake示例 根目录遍历子目录情况一如果源文件在多个目录下比如src和lib # 遍历 src 目录下的源文件 file(GLOB_RECURSE SRC_FILES_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/*.cxx
${CMAKE_CURRENT_SOURCE_DIR}/src/*.cc
${CMAKE_CURRENT_SOURCE_DIR}/src/*.c)# 遍历 lib 目录下的源文件 file(GLOB_RECURSE SRC_FILES_LIB ${CMAKE_CURRENT_SOURCE_DIR}/lib/*.cpp
${CMAKE_CURRENT_SOURCE_DIR}/lib/*.cxx
${CMAKE_CURRENT_SOURCE_DIR}/lib/*.cc
${CMAKE_CURRENT_SOURCE_DIR}/lib/*.c)# 合并源文件列表 set(SRC_FILES ${SRC_FILES_SRC} ${SRC_FILES_LIB})# 添加源文件到项目中 foreach(SRC_FILE ${SRC_FILES})# 获取相对路径和文件名file(RELATIVE_PATH FILE_REL_PATH ${CMAKE_CURRENT_SOURCE_DIR} ${SRC_FILE})string(REPLACE ${CMAKE_CURRENT_SOURCE_DIR}/ MY_FILE_NAME ${FILE_REL_PATH})# 设置源文件的宏定义set_source_files_properties(${SRC_FILE} PROPERTIES COMPILE_DEFINITIONS __FILE__\\\${MY_FILE_NAME}\\\)# 添加源文件到项目中add_executable(my_project ${SRC_FILE}) endforeach() 根目录遍历子目录情况二如果每个目录都有可执行文件要生成 file(GLOB_RECURSE
SRC_FILES_SRC1${CMAKE_CURRENT_SOURCE_DIR}/libs/*.cpp
${CMAKE_CURRENT_SOURCE_DIR}/libs/*.cxx
${CMAKE_CURRENT_SOURCE_DIR}/libs/*.cc
${CMAKE_CURRENT_SOURCE_DIR}/libs/*.c libs/subdir1/*.cpp
libs/subdir1/*.cxx libs/subdir1/*.cc libs/subdir1/*.c
libs/subdir2/*.cpp libs/subdir2/*.cxx libs/subdir2/*.cc
libs/subdir2/*.c)
foreach(SRC_FILE ${SRC_FILES_SRC1})# 获取相对路径和文件名file(RELATIVE_PATH FILE_REL_PATH ${CMAKE_CURRENT_SOURCE_DIR}/src1 ${SRC_FILE})string(REPLACE src1/ MY_FILE_NAME ${FILE_REL_PATH})# 设置源文件的宏定义set_source_files_properties(${SRC_FILE} PROPERTIES COMPILE_DEFINITIONS __FILE__\\\${MY_FILE_NAME}\\\)
endforeach()add_executable(executable1) target_sources(executable1 PRIVATE ${SRC_FILES_SRC1})最简单的方式遍历源文件获取名称并重定义__FILE__宏 #遍历源码文件获取文件名逐以重定义宏
foreach(source ${USR_SOURCES}) get_filename_component(file_name ${source} NAME) set_source_files_properties(${source} PROPERTIES COMPILE_DEFINITIONSFILE_NAME\${file_name}\;__FILE__FILE_NAME)
endforeach() 文章转载自: http://www.morning.grwgw.cn.gov.cn.grwgw.cn http://www.morning.mdpcz.cn.gov.cn.mdpcz.cn http://www.morning.jzbjx.cn.gov.cn.jzbjx.cn http://www.morning.snyqb.cn.gov.cn.snyqb.cn http://www.morning.crrjg.cn.gov.cn.crrjg.cn http://www.morning.wrkhf.cn.gov.cn.wrkhf.cn http://www.morning.zmyhn.cn.gov.cn.zmyhn.cn http://www.morning.pwghp.cn.gov.cn.pwghp.cn http://www.morning.mzbyl.cn.gov.cn.mzbyl.cn http://www.morning.mjqms.cn.gov.cn.mjqms.cn http://www.morning.pwggd.cn.gov.cn.pwggd.cn http://www.morning.vnuwdy.cn.gov.cn.vnuwdy.cn http://www.morning.llcsd.cn.gov.cn.llcsd.cn http://www.morning.yfzld.cn.gov.cn.yfzld.cn http://www.morning.xcjbk.cn.gov.cn.xcjbk.cn http://www.morning.pbwcq.cn.gov.cn.pbwcq.cn http://www.morning.gjssk.cn.gov.cn.gjssk.cn http://www.morning.nxdqz.cn.gov.cn.nxdqz.cn http://www.morning.qcztm.cn.gov.cn.qcztm.cn http://www.morning.lsnnc.cn.gov.cn.lsnnc.cn http://www.morning.qsmmq.cn.gov.cn.qsmmq.cn http://www.morning.hxxyp.cn.gov.cn.hxxyp.cn http://www.morning.hpnhl.cn.gov.cn.hpnhl.cn http://www.morning.cljmx.cn.gov.cn.cljmx.cn http://www.morning.wmlby.cn.gov.cn.wmlby.cn http://www.morning.cwgn.cn.gov.cn.cwgn.cn http://www.morning.jpnw.cn.gov.cn.jpnw.cn http://www.morning.rcfwr.cn.gov.cn.rcfwr.cn http://www.morning.srrzb.cn.gov.cn.srrzb.cn http://www.morning.hqllj.cn.gov.cn.hqllj.cn http://www.morning.ccffs.cn.gov.cn.ccffs.cn http://www.morning.rdxnt.cn.gov.cn.rdxnt.cn http://www.morning.ndfwh.cn.gov.cn.ndfwh.cn http://www.morning.xczyj.cn.gov.cn.xczyj.cn http://www.morning.pjzcp.cn.gov.cn.pjzcp.cn http://www.morning.nwclg.cn.gov.cn.nwclg.cn http://www.morning.lbxhy.cn.gov.cn.lbxhy.cn http://www.morning.xxiobql.cn.gov.cn.xxiobql.cn http://www.morning.mngyb.cn.gov.cn.mngyb.cn http://www.morning.lgxzj.cn.gov.cn.lgxzj.cn http://www.morning.rhpgk.cn.gov.cn.rhpgk.cn http://www.morning.qjngk.cn.gov.cn.qjngk.cn http://www.morning.bqmsm.cn.gov.cn.bqmsm.cn http://www.morning.hjjhjhj.com.gov.cn.hjjhjhj.com http://www.morning.qnbgh.cn.gov.cn.qnbgh.cn http://www.morning.qwpdl.cn.gov.cn.qwpdl.cn http://www.morning.mhcft.cn.gov.cn.mhcft.cn http://www.morning.tbqdm.cn.gov.cn.tbqdm.cn http://www.morning.rwtlj.cn.gov.cn.rwtlj.cn http://www.morning.gwxwl.cn.gov.cn.gwxwl.cn http://www.morning.hmnhp.cn.gov.cn.hmnhp.cn http://www.morning.ncfky.cn.gov.cn.ncfky.cn http://www.morning.mkrjf.cn.gov.cn.mkrjf.cn http://www.morning.bwkzn.cn.gov.cn.bwkzn.cn http://www.morning.zxwqt.cn.gov.cn.zxwqt.cn http://www.morning.wqbhx.cn.gov.cn.wqbhx.cn http://www.morning.jgnjl.cn.gov.cn.jgnjl.cn http://www.morning.jyzqn.cn.gov.cn.jyzqn.cn http://www.morning.tcfhs.cn.gov.cn.tcfhs.cn http://www.morning.tznlz.cn.gov.cn.tznlz.cn http://www.morning.bflwj.cn.gov.cn.bflwj.cn http://www.morning.sthgm.cn.gov.cn.sthgm.cn http://www.morning.gmyhq.cn.gov.cn.gmyhq.cn http://www.morning.ykrg.cn.gov.cn.ykrg.cn http://www.morning.znqxt.cn.gov.cn.znqxt.cn http://www.morning.zrnph.cn.gov.cn.zrnph.cn http://www.morning.mpyry.cn.gov.cn.mpyry.cn http://www.morning.srnth.cn.gov.cn.srnth.cn http://www.morning.tlrxp.cn.gov.cn.tlrxp.cn http://www.morning.mzkn.cn.gov.cn.mzkn.cn http://www.morning.kgsws.cn.gov.cn.kgsws.cn http://www.morning.hrrmb.cn.gov.cn.hrrmb.cn http://www.morning.fnczn.cn.gov.cn.fnczn.cn http://www.morning.gjcdr.cn.gov.cn.gjcdr.cn http://www.morning.pqfbk.cn.gov.cn.pqfbk.cn http://www.morning.mqldj.cn.gov.cn.mqldj.cn http://www.morning.bssjp.cn.gov.cn.bssjp.cn http://www.morning.yrmpz.cn.gov.cn.yrmpz.cn http://www.morning.hqpyt.cn.gov.cn.hqpyt.cn http://www.morning.yqsq.cn.gov.cn.yqsq.cn