• C/C++中#和##的宏以及进行“花里胡哨“的命名及其应用


    目录

    写在前面

    认识宏  # 和 ##

    #的学习

    ##的学习

    实战


    写在前面

            最近依然在嵌入式遨游,以及加深对free rt os 源码以及内核的理解。以及为了解决学习工作中分布式设备的命名问题。于是就想到了  #和##这两个宏。

    认识宏  # 和 ##

    既然都是宏,则它们在编译的第一个阶段也就是预编译阶段被替换掉,在程序的运行过程中不存在宏。

    #的学习

    试想我能不能在字符串中插入变量。答案就是#。它必须放在变量前,把变量字符串化。 #A 为 "A" (A必须在编译器被确定) 

    作用:

    • 字符串化,在字符串中插入参数值。
    • 连接作用

    #define  DEV(X)   "DEV"X             // 于是DEV(1)   就为 "DEV1"

    1. #define dev(x) "dev("#x")"
    2. #define mytest(x) "test"#x
    3. int main() {
    4. std::cout << dev(1) << "\r\n";
    5. std::cout << mytest(21) << "\r\n";
    6. }

    结果

     从结果看到确实能把参数字符串化并它们拼接在一起。

    但是:#的单独使用并不能连接字符串。 正如上面所提到到,他必须要放在参数前,可以通过以下方式连接两个字符串.

    #define test3(x)  "hello"#x"world"     

    测试:std::cout<

    而当我想用这样的方式两个两个以上的字符串的宏时却发现不行。

    比如这样的形式会报错(编译不通过,因为不认识 xstr2)

    #define str1 "hello"
    #define str2 "world"
    #define test3(x)  str1#xstr2

    这时就需要 宏 ##字符串出马了!

    str1#x##str2    //把三个字符串拼接

    1. #define str1 "hello"
    2. #define str2 "world"
    3. #define test3(x) str1#x##str2
    4. int main() {
    5. std::cout << test3() << "\r\n";
    6. }

      试想既然是在预编译就会被替换,哪#能不能变函数呢?

    比如

    1. void fun1() {
    2. std::cout << "fun1\r\n";
    3. }
    4. #define finaltest(X) fun#X()
    5. int main() {
    6. finaltest(1);
    7. }

    结果报错,原因是fun是未定义的标识符,而把宏改成"fun"#x"()",则更加不行,这从根本上就是字符串啊。。。至于我为什么要这么做,这看上有些笨拙,当这正是认识的过程,当然,这也为我引入后面的 宏 “##”

    ##的学习

    有了上面的认识,就知道 宏 ##可以连接任意的字符串,可以连接任意字符串的宏。同时它可以做标识符、

    作用

    • 连接任意字符串
    • 做标识符。(花里胡哨用)

    比如连接字符串

    1. #define str1 "hhhhhh"
    2. #define mytest(x) "hello"#x##"world"##"my name is yzh"##str1
    3. void fun1() {
    4. std::cout << "fun1\r\n";
    5. }
    6. int main() {
    7. std::cout << mytest(2) << "\r\n";
    8. }

    这个VS上提升找不到用户定义的文本运算符,当依然能够编译成功并运行。

    比如做标识符

    1. #define finaltest(x) fun##x
    2. #define fun(x) var##x
    3. void fun1() {
    4. std::cout << "fan1\r\n";
    5. }
    6. int main() {
    7. int fun(1) = 21;
    8. var1 = 999;
    9. std::cout << fun(1) << "\r\n";
    10. finaltest(1)();
    11. }

    运行 

    实战

    在不同的网络下,不同的设备连接不同的网络,订阅各自由自己的名字组成的主题,发布由自己的名字组成的主题。

    比如 ,设备名是ESP1  ,订阅 dev/set/ESP1 ,发布 dev/date/ESP1 ,发布 callback/ESP1 。同时,能方便更改所连接的WIFI,所连接的服务器地址(ip)以及连接服务器所对应的端口。

    WIFI账号和密码,服务器地址,端口这些用简单的宏定义就行了。

    比如

    #define WIFINAME   "WIFI" 

     关键在于要把它们组成AT指令的报文,所以就有固 定的格式,对命令的每个部分都有明确的要求。这时候  宏 # 和  ##就派上用场了。

    1. #define WIFINAME "rookie" //WIFI用户名
    2. #define WIFIPWD "yy061457" //WIFI密码
    3. #define MQTTNAME "admin" //服务器用户名
    4. #define MQTTPWD "061457" //服务器密码
    5. #define MQTTPORT "1883" //服务器端口
    6. #define MQTTURL "192.168.1.13" //服务器地址
    7. #define DEVNAME(X) "ESP"#X //设备名
    8. #define REALNAME DEVNAME(1) //真正要用到的设备名
    9. #define PUBTOPICALL "callback/"##REALNAME //发布主题
    10. #define SUBTOPICCMD "dev/set/"##REALNAME //订阅主题
    11. #define PUBTOPICDATE "dev/date/"##REALNAME //订阅主题名
    12. extern __IO u8 mqttstate;
    13. //订阅主题格式
    14. #define SUBTOPIC "AT+MQTTSUB=0,\"%s\",0\r\n"
    15. //发布对应主题对应信息格式
    16. #define PUBTOPIC "AT+MQTTPUB=0,\"%s\",\"%s\",0,0\r\n"
    17. //连接对应WIFI 账号 密码
    18. #define CONNECTWIFI "AT+CWJAP=\
    19. \""##WIFINAME##"\",\
    20. \""##WIFIPWD##"\"\r\n"
    21. //清除MQTT连接信息
    22. #define CLEANMQTTINFO "AT+MQTTCLEAN=0\r\n"
    23. //连接EMQX服务器的本地登录账号和密码
    24. #define LOGINMQTT "AT+MQTTUSERCFG=0,1,\""##REALNAME##"\",\""##MQTTNAME##"\",\
    25. \""##MQTTPWD##"\",\
    26. 0,0,\"\"\r\n\
    27. "
    28. //连接本地EMQX 下的mqtt服务器地址 设置断开自动重连
    29. #define CONNECTMQTT "AT+MQTTCONN=0,\""##MQTTURL##"\","##MQTTPORT##",1\r\n"

    另外,在free rt os ,以及stm32中的库里经常用到 # 和##来封装库函数。

  • 相关阅读:
    如何将网站部署到浏览器?
    DataGrip 2023 年下载、安装教程、亲测可用
    神经网络卷积层
    BUUCTF reverse3 1
    java毕业设计奇妙店铺电子商务网站源码+lw文档+mybatis+系统+mysql数据库+调试
    【SA8295P 源码分析】105 - QNX MISC分区读写、切换A/B启动槽、读取开机次数命令 swdl_utils 介绍 及 祼分区读写 代码实现
    力扣:11-盛最多水的容器
    LeetCode 11. 盛最多水的容器
    【06】Spring源码-分析篇-ApplicationContext
    【LeetCode】15. 三数之和
  • 原文地址:https://blog.csdn.net/PHILICS7/article/details/127797417