C语言宏定义中L##"STRING"

本文详细解析了USB字符串描述符的结构,包括bLength和bDescriptorType字段的作用,以及如何在C语言中使用宏定义实现字符串到UNICODE编码的转换。探讨了gcc编译器下wchar_t类型的编译选项。

在USB字符串描述符中
在这里插入图片描述
bLength为描述符长度,bDeorType为描述符类型,字符编码统一采用UNICODE编码,UNICODE采用两个字节字节表示一个字符,如果是英语字符的话,那就很简单了,直接在ASCII码前面补上一个为0x00的字节数据就组成UNICODE编码了。

但是在C编译器中,
#define WIDE_STRING(string) _WIDE_STRING(string)
#define _WIDE_STRING(string) L##string

通过WIDE_STRING(“string”)配合wchar可以将“string”直接变成UNICODE。

#define WIDE_STRING(string) _WIDE_STRING(string)
#define _WIDE_STRING(string) L##string

#define USBD_STRING_DESC(string)
(uint8_t *)&(struct {
uint8_t _len;
uint8_t _type;
wchar_t _data[sizeof(string)];
}) {
sizeof(WIDE_STRING(string)) + 2U - 2U,
USB_DESCTYPE_STRING,
WIDE_STRING(string)
}

L"string"表示Unicode字符串,是const WCHAR *类型,一个字符有16位。而_T(“string”)的含义和_UNICODE宏定义有关,如果_UNICODE定义,则_T(“string”)和L"string"一样,否则_T(“string”)是普通字符串。

char buff[] = “string”;
WCHAR buff[]=L"string"

同时注意,在gcc中,wchar_t可以选择编译成2字节和4字节,编译选项为:-fshort-wchar

<think>好的,我现在需要解释C语言宏定义中'#'的作用。首先,用户的问题是关于宏中的#符号,我需要确保自己正确理解这个符号的功能。根据之前的引用资料,特别是引用[2]提到,#的功能是将其后面的参数进行字符串化操作,即在宏变量替换后上双引号。比如,DECLARE_CMD(test_string)会被替换成"test_string"。 接下来,我要考虑如何组织这个解释。可能需要先介绍基本概念,再举例子说明。引用[4]中的代码示例可能会有帮助,比如P(A)定义为#A,这样在代码中使用P(a)就会变成"a"。同时,引用[3]中的例子展示了如何用宏定义字符串,比如HELLO和WORLD组合输出。 然后,需要区分#和##的不同,虽然用户问的是#,但可能需要简要提到##作为对比,但重点还是放在#上。例如,在引用[4]中,FOO(arg)使用##来连接my和arg,生成my1这样的标识符,而#则是用来字符串化参数。 还要注意用户可能混淆#和字符串连接的情况,需要澄清。例如,在宏中使用#时,参数会被直接转换为字符串,而不是进行任何运算。例如,P(a+b)会被转换为"a+b"而不是计算后的值。 可能需要检查是否有其他用途或注意事项。比如,宏展开的顺序,或者参数中含有特殊字符时的处理,但根据引用资料,主要功能是字符串化,所以应该保持解释简洁。 最后,确保回答结构清晰,分点说明,并给出示例代码,这样用户更容易理解。同时,生成相关问题时要围绕宏定义的其他符号或高级用法展开,帮助用户深入探索。</think>C语言宏定义中`#`的作用可分为以下三个层次进行解析: ### 一、基础作用 `#`符号在宏定义中称为**字符串化运算符**,其核心功能是将宏参数转换为字符串字面量。例如: ```c #define STRINGIFY(x) #x printf("%s", STRINGIFY(Hello)); // 输出"Hello" ``` 此时宏参数`Hello`经过`#`处理后会变成字符串`"Hello"`[^2][^4]。 ### 二、特殊场景处理 1. **保留空白符**: 当宏参数包含空格时,`#`会保留原始格式: ```c STRINGIFY(a b); // 转换为"a b" ``` 2. **嵌套宏展开**: 需要双重展开时需配合中间宏: ```c #define _STR(x) #x #define STR(x) _STR(x) STR(__LINE__); // 先展开__LINE__为行号,再转换为字符串 ``` 3. **运算符处理**: 对表达式参数会保留运算符: ```c STRINGIFY(a+b); // 转换为"a+b"而非运算结果 ``` ### 三、工程应用示例 1. **调试日志**: ```c #define DEBUG_LOG(fmt, ...) \ printf("[DEBUG] %s:%d " fmt, __FILE__, __LINE__, ##__VA_ARGS__) DEBUG_LOG("value=%d", 42); // 输出:[DEBUG] test.c:42 value=42 ``` 这里`#`虽未直接使用,但展示了与`##`结合处理可变参数的典型用法[^4]。 2. **枚举转字符串**: ```c #define ENUM_CASE(val) case val: return #val const char* enum_to_str(int e) { switch(e) { ENUM_CASE(ERROR_NONE); ENUM_CASE(ERROR_INVALID); } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值