【问题标题】:Create string and wide string literals from a single definition从单个定义创建字符串和宽字符串文字
【发布时间】:2019-09-29 20:53:21
【问题描述】:

有时需要为 char *wchar_t * 类型创建具有相同值的字符串文字(例如,在 Windows 中开发时)。一个简单的方法是把定义写两次:

const char *my_string = "Hello World";
const wchar_t *my_wide_string = L"Hello World";

问题是如果我们需要改变字符串,而不是只改变一个地方,两行都需要更新,经常会导致拼写错误和错误。理想情况下,文字应该只出现一次,并且两个变量都由它填充。

我们可以定义char 变量并在运行时将其转换为wchar_t 版本。但是,最好避免运行时成本,因为字面量在编译时已经可用。

我想使用标记粘贴操作符,但不能让它工作,因为它只接受另一个字符串文字:

#define my_string "Hello World"
#define make_wide(str) L##str
#define my_wide_string make_wide(my_string)  // expand to Lmy_string instead of L"Hello World"

我不确定是否可以使用constexpr 使其工作?

【问题讨论】:

    标签: c++ windows macros string-literals widechar


    【解决方案1】:

    您只需要另一个宏,以便在粘贴之前扩展宏的参数:

    #include <wchar.h>
    
    #define my_string "Hello World"
    
    #define WidenHelper(x)  L##x
    #define Widen(x)        WidenHelper(x)
    
    const char *plain   = my_string;
    const wchar_t *wide = Widen(my_string);
    

    【讨论】:

      【解决方案2】:

      您不太可能希望这两个版本都采用适当的设计。无论如何,这两种类型(charwchar_t)不兼容(8/16 位)所以你不能在编译级别这样做。

      设计一个使用 wchar_t 并仅在必要时转换为 char 的类。您为此使用WideCharToMultiByte

      将您的整个应用程序设计为仅使用宽字符,并且在序列化时仅使用 UTF-8 格式。

      【讨论】:

      • 正确设计:一种情况是我的应用程序是多字节的,但某些 API/库只接受 wchar_t*(幸运的是只接受这些文字)。不兼容:我知道它们是完全不同的表示,但我希望编译器可以为我做计算,而不是要求我写两次相同的值。
      • 不能。重新设计您的应用程序以使用宽表单(并完全退出 char 版本),或者,如果您不能这样做,请创建一个可以根据请求切换的转换器类。
      • 考虑到 char 实际上是 UTF-8 (utf8everywhere.org) 的首选,甚至 Windows 也在添加 UTF-8 支持 (en.wikipedia.org/wiki/Unicode_in_Microsoft_Windows#UTF-8),我试图继续使用 char .
      • 大多数系统使用宽字符串。 (Windows、Java、Android、iOS)。 UTF-8 通常用于 nix 和数据交换。它速度较慢,并且无法通过字符串进行迭代。在 Windows 应用程序中,始终使用宽字符串。 UTF-8根本不是无处不在。
      • @MichaelChourdakis UTF8 是当今处理 unicode 的首选方式。 16bit 字符也有同样的问题,因为有超过 2^16 个代码点,所以有些字符也需要超过一个字节。
      【解决方案3】:

      由于您使用的是 Windows,因此您可以在 crtdefs.h 中使用 _STR2WSTR,当您使用 #include &lt;windows.h&gt; 时会包含该 _STR2WSTR。还有__FILEW____FUNCTIONW__是用普通字符串变体做的例子

      /* error reporting helpers */
      #define __STR2WSTR(str)    L##str
      #define _STR2WSTR(str)     __STR2WSTR(str)
      
      #define __FILEW__          _STR2WSTR(__FILE__)
      #define __FUNCTIONW__      _STR2WSTR(__FUNCTION__)
      

      更新:

      后来的 CRT 版本已将其更改为 _CRT_WIDE

      #define _CRT_WIDE_(s) L ## s
      #define _CRT_WIDE(s) _CRT_WIDE_(s)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-07-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-11-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多