c - 有没有办法在 C 中的预处理器或编译时检测 u8"" 文字?
问题描述
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
部分,在这种情况下我返回一个用于打印的字符串:
#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")
该宏仅检查预处理器标记中的第一个字符是否为 a "
。它可以做得更高级一些,'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
推荐阅读
- android - 尝试将事件添加到 Android 日历时出错
- ios - 在 iOS 上,0x0000000000000026、0x000000000000001c、0x000000000000005a 是标记指针的示例吗?
- spring-boot - 在 Spring Boot 中覆盖子类的链接路径
- twilio - 调用未完成时,Twilio 调用对象如何报告价格?
- grails - Grails:是否可以从 afterInsert() 或 afterUpdate() 查询更新后的保存对象?
- python - 从模板运行时参数、Python、Apache Beam、Dataflow 命名 BigQuery 表
- mdx - Mdx,大于 String 而不是 Numeric (Saiku)
- flask - Flask UWSGI ModuleNotFound
- javascript - 快照测试使用 PropTypes 的 React 连接组件
- python-3.x - 在 glob 中使用隐式路径名参数