是否有广泛可用的“__FILE__”宽字符变体

Is there widely-available wide-character variant of `__FILE__`?

本文关键字:FILE 字符 是否      更新时间:2023-10-16

人们通常可以在C++程序中使用__LINE____FILE__,其中包含许多工具链,包括GCC。

GCC 下的__LINE__计算结果为 int 型表达式;
__FILE__计算结果为一个 char const[N]其中 N 是适当的值。

  • 是否有任何主要工具链提供等效于具有类型wchar const[N]__FILE__
  • 如果是这样,它是什么?

您可以制作自己的WFILE

#define WIDE2(x) L##x
#define WIDE1(x) WIDE2(x)
#define WFILE WIDE1(__FILE__)

使用非 ASCII 字符和文件名马克.cpp进行测试:

#include <stdio.h>
#include <io.h>
#include <fcntl.h>
#define WIDE2(x) L##x
#define WIDE1(x) WIDE2(x)
#define WFILE WIDE1(__FILE__)
int main() {
    _setmode(_fileno(stdout), _O_U16TEXT); // required for Unicode output to console
    wprintf(L"%sn", WFILE);
}

演示(从cmd运行.exe并安装了中文支持(:

C:>cl /W4 /nologo 马克.cpp
马克.cpp
C:>马克.exe
马克.cpp

使用:

WIDE(MEXPAND(__FILE__))

WIDE(STRINGIFY(__LINE__))

或者将__LINE__替换为需要字符串化的任何内容,并将__FILE__替换为要加宽的任何宏字符串文本。

使用以下定义:

#define STRINGIFY2(m) #m
#define MEXPAND(m) m
#define STRINGIFY(m) STRINGIFY2(m)
#define WIDE(m) L ## m

用法示例:

#define AssertBreakMethod DebugBreak
#define AssertBreakForce(expr) 
  do 
  { 
    if (!(expr)) 
    { 
      OutputDebugStringW(WIDE(MEXPAND(__FILE__)) 
          WIDE("(") WIDE(STRINGIFY(__LINE__)) 
          WIDE("): Assertion failed: ") 
          WIDE(#expr) WIDE("n")); 
      AssertBreakMethod(); 
    } 
  } 
  while (0)

请注意,OutputDebugString 的整个参数在编译时静态组装成单个字符串文本。

一个宏字符串化的诀窍是通过另一个宏传递它。当__FILE__传递给MEXPAND时,它会在那时展开。 MEXPAND返回其参数,该参数现在是一个字符串。然后,将前导L放在那里以使其宽是合法的。

STRINGIFY执行相同的技巧,它会将其参数传递到STRINGIFY2,这会将参数扩展为行号(此时看起来像整数(,然后STRINGIFY2#符号放在它前面,将整数字符串化。

在Visual Studio中,只需用_T()将其括起来,例如:

TRACE( _T("function = %s"), _T(__FUNCTION__);

我会把这个答案作为对早期回复的评论,但由于没有至少 50 个声誉来评论,所以不允许......

在 Visual Studio 中,_T(__FILE__(

不会扩展到L__FILE__,除非您在 tchar.h 头文件中修改其_T的标准定义。 _T(__FILE__( 和 _T(__FUNCTION__( 在 5 年前工作,如果您正在寻找当前文件和函数的广泛版本,今天仍然有效。

_T(x( 定义为 __T(x(,当定义 _UNICODE 时定义为 L##x,否则定义为 x。因此,_T(__FILE__(扩展到类似__T("my_file.c"(,然后根据_UNICODE扩展到L"my_file.c"或"my_file.c"。在声称它们不起作用之前测试它们很有用。

例如使用 const auto name = L"" __FUNCTION__;