有没有办法在 C 的预处理器或编译时检测 u8"" 文字?
Is there a way to detect u8"" literals at preprocessor or compile time in C?
C11现在提供了几种字符串字面量:
"old school literals"
u8"UTF-8 encoded literals"
u"char16_t encoded literals"
U"char32_t encoded literals"
L"wchar_t literals, whatever size it may be"
由于涉及不同的类型,可以使用 _Generic()
表达式来区分不同大小的文字。遗憾的是,原生 "quoted literals"
和 u8"quoted literals."
之间没有大小和类型差异
我想知道是否可以使用预处理器魔法,但似乎 GCC 要么将 u8"text"
视为不可分割的标记,要么在早期阶段吞噬了 u8
。无论如何,我无法用宏获取“u8”前缀。 :-(
所以,我想知道:有没有什么方法可以在不“只知道”的情况下区分本机编码文字和 UTF-8 编码文字?
上下文是我的库代码,它希望将传递的字符串智能地转换为 UTF-8。如果我可以将调用包装在一个宏中,以确定我是否需要对字符串进行转码,那就太好了。 (否则,当然,我必须依赖用户。而且你知道他是多么白痴。)
您可以使用 _Generic
然后做一些预处理器技巧来区分。首先是 _Generic
部分,在本例中我将 return 用于打印的字符串:
#define LITERAL_TYPE(s) \
_Generic((s), \
char*: U8_TYPE(s), \
wchar_t*: "wchar_t", \
char16_t*: "char16_t", \
char32_t*: "char32_t")
然后 U8_TYPE
宏:
#define U8_TYPE(s) (#s[0]=='\"'? "old school":"u8")
这个宏只是检查预处理器标记中的第一个字符是否是 "
。它可以做得更高级一点,并寻找 'u'
和 '8'
以及一些 &&
检查,尽管你也必须检查结束 '"'
大小写,这样您就不会越界访问。
测试代码:
#include <stdio.h>
#include <wchar.h>
#include <uchar.h>
#define U8_TYPE(s) (#s[0]=='\"'? "old school":"u8")
#define LITERAL_TYPE(s) \
_Generic((s), \
char*: U8_TYPE(s), \
wchar_t*: "wchar_t", \
char16_t*: "char16_t", \
char32_t*: "char32_t")
int main(void)
{
puts(LITERAL_TYPE("hello"));
puts(LITERAL_TYPE(L"hello"));
puts(LITERAL_TYPE(u8"hello"));
puts(LITERAL_TYPE(u"hello"));
puts(LITERAL_TYPE(U"hello"));
}
输出:
old school
wchar_t
u8
char16_t
char32_t
C11现在提供了几种字符串字面量:
"old school literals"
u8"UTF-8 encoded literals"
u"char16_t encoded literals"
U"char32_t encoded literals"
L"wchar_t literals, whatever size it may be"
由于涉及不同的类型,可以使用 _Generic()
表达式来区分不同大小的文字。遗憾的是,原生 "quoted literals"
和 u8"quoted literals."
我想知道是否可以使用预处理器魔法,但似乎 GCC 要么将 u8"text"
视为不可分割的标记,要么在早期阶段吞噬了 u8
。无论如何,我无法用宏获取“u8”前缀。 :-(
所以,我想知道:有没有什么方法可以在不“只知道”的情况下区分本机编码文字和 UTF-8 编码文字?
上下文是我的库代码,它希望将传递的字符串智能地转换为 UTF-8。如果我可以将调用包装在一个宏中,以确定我是否需要对字符串进行转码,那就太好了。 (否则,当然,我必须依赖用户。而且你知道他是多么白痴。)
您可以使用 _Generic
然后做一些预处理器技巧来区分。首先是 _Generic
部分,在本例中我将 return 用于打印的字符串:
#define LITERAL_TYPE(s) \
_Generic((s), \
char*: U8_TYPE(s), \
wchar_t*: "wchar_t", \
char16_t*: "char16_t", \
char32_t*: "char32_t")
然后 U8_TYPE
宏:
#define U8_TYPE(s) (#s[0]=='\"'? "old school":"u8")
这个宏只是检查预处理器标记中的第一个字符是否是 "
。它可以做得更高级一点,并寻找 'u'
和 '8'
以及一些 &&
检查,尽管你也必须检查结束 '"'
大小写,这样您就不会越界访问。
测试代码:
#include <stdio.h>
#include <wchar.h>
#include <uchar.h>
#define U8_TYPE(s) (#s[0]=='\"'? "old school":"u8")
#define LITERAL_TYPE(s) \
_Generic((s), \
char*: U8_TYPE(s), \
wchar_t*: "wchar_t", \
char16_t*: "char16_t", \
char32_t*: "char32_t")
int main(void)
{
puts(LITERAL_TYPE("hello"));
puts(LITERAL_TYPE(L"hello"));
puts(LITERAL_TYPE(u8"hello"));
puts(LITERAL_TYPE(u"hello"));
puts(LITERAL_TYPE(U"hello"));
}
输出:
old school
wchar_t
u8
char16_t
char32_t