从单个定义创建字符串和宽字符串文字
Create string and wide string literals from a single definition
有时需要为 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
让它工作?
您不太可能希望两个版本都采用适当的设计。无论如何,这两种类型(char
和wchar_t
)不兼容(8/16位)所以你不能在编译级别做到这一点。
设计一个 class 使用 wchar_t 并仅在必要时转换为 char。为此,您使用 WideCharToMultiByte。
将整个应用程序设计为仅使用宽字符,并且在序列化时仅使用 UTF-8 格式。
您只需要另一个宏,以便在粘贴之前扩展宏的参数:
#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);
因为你在 Windows,你可以在 crtdefs.h 中使用 _STR2WSTR
,当你 #include <windows.h>
时它会被包含在内。还有 __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)
有时需要为 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
让它工作?
您不太可能希望两个版本都采用适当的设计。无论如何,这两种类型(char
和wchar_t
)不兼容(8/16位)所以你不能在编译级别做到这一点。
设计一个 class 使用 wchar_t 并仅在必要时转换为 char。为此,您使用 WideCharToMultiByte。
将整个应用程序设计为仅使用宽字符,并且在序列化时仅使用 UTF-8 格式。
您只需要另一个宏,以便在粘贴之前扩展宏的参数:
#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);
因为你在 Windows,你可以在 crtdefs.h 中使用 _STR2WSTR
,当你 #include <windows.h>
时它会被包含在内。还有 __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)