关于C语言中的连接符的用法 # ## macro stringize

首先面向需求,小工程、代码不多、版本还挺多...

打算用宏控制开关选项、然后通过一长串

#if

#elif

...

#endif

来控制生成版本号、而且还要根据兼容性跟细小变更做三级版本号....

所以就需要一个版本号拼接、明显,应该是编译期能做完的事情。

--------需求完毕--------

C语言宏定义应该是可完成的、在代码执行期间更加是没问题的。

虽然用string.h也可以完成拼接。

不舒服斯基...

初步查找 使用 # 和##,可以完成、进一步查找发现有个#@ 是什么鬼... 部分编译器不支持

经过初步试用# 会直接把传递进来的macro直接变成string,#@理论上是实现我需要的功能,然而并不支持

---------------神奇的分割线-------------------------

进一步查找stringize site:gcc.gnu.org

找到页面

3.4 Stringification

https://gcc.gnu.org/onlinedocs/cpp/Stringification.html

鉴于是blog,就不贴原文了,又需要的自己去看。

结论:

If you want to stringify the result of expansion of a macro argument, you have to use two levels of macros.

#define xstr(s) str(s)
     #define str(s) #s
     #define foo 4
     str (foo)
          ==> "foo"
     xstr (foo)
          ==> xstr (4)
          ==> str (4)
          ==> "4"

结合## 无限可能出来了

#define xstr(s) str(s)      //copy from https://gcc.gnu.org/onlinedocs/cpp/Stringification.html
#define str(s) #s

#define _STRING_(_X_)           xstr(_X_)    //convert from macro to string
#define BSP_HARD_REVERSION      1.0.0
#define SW_FIRST_VERSION        8
#define SW_MID_VERSION          800
#define SW_LAST_VERSION         021
#define SW_FULL_VSERSION        SW_FIRST_VERSION##.##SW_MID_VERSION##.##SW_LAST_VERSION
#define HW_VERSION_STRING       _STRING_(BSP_HARD_REVERSION)
#define SW_VERSION_STRING       _STRING_(SW_FULL_VSERSION)

static const char hw_rev[] = HW_VERSION_STRING;      //hw_rec config by boards.h
static const char fw_rev[] = "8.0.0";
static const char sw_rev[] = SW_VERSION_STRING;

#undef str
#undef xstr
#undef _STRING_

OK 到这里我需要的功能已经搞定。大家随便拿个调试工具看看就可以了,确实是OK的

仔细研究了下实现原理,感觉自己对宏定义的理解又深入了一个层次...其实也没有那么复杂

s is stringified when it is used in str, so it is not macro-expanded first. But s is an ordinary argument to xstr, so it is completely macro-expanded before xstr itself is expanded (see Argument Prescan). Therefore, by the time str gets to its argument, it has already been macro-expanded.

原文地址

http://my.oschina.net/mummy108/blog/510439

时间: 2024-10-13 19:50:19

关于C语言中的连接符的用法 # ## macro stringize的相关文章

Java C# C语言中的占位符

一般拼接一段字符串在编程中是很常见的事,下面简单做个总结: 什么是占位符?占位符就是先占住一个固定的位置,等着你再往里面添加内容的符号. 1.Java中处理方法: package com.amos; import java.text.MessageFormat; /** * Created by amosli on 14-7-24. */ public class Test { public static void main(String args[]) { //拼接一段string 常用的方法

C宏定义中的连接符"##"和字符串化操作符"# "及变参宏"..."

C语言中如何使用宏C(和C++)中的宏(Macro)属于编译器预处理的范畴,属于编译期概念(而非运行期概念). 1.宏定义中字符串化操作符#: #的功能是将其后面的宏参数进行字符串化操作,意思就是对它所应用的宏变量通过替换后在其左右各加上一个双引号. 例如: #define WARN_IF(EXPR)do { if (EXPR) fprintf(stderr, "Warning: " #EXPR "\n");} while(0) 上面代码中的反斜线\主要用来转译换行

C语言中关于scanf函数的用法

scanf()函数的控制串 函数名: scanf 功 能: 执行格式化输入 用 法: int scanf(char *format[,argument,...]); scanf()函数是通用终端格式化输入函数,它从标准输入设备(键盘) 读取输入的信息.可以读入任何固有类型的数据并自动把数值变换成适当的机内格式. 其调用格式为: scanf("<格式化字符串>",<地址表>); scanf()函数返回成功赋值的数据项数,出错时则返回EOF. 其控制串由三类字符构成

C语言宏定义##连接符和#符的使用(MFC就是靠##自动把消息和消息函数对应起来了,借助宏来减少switch case代码的编写量)

C语言中如何使用宏C(和C++)中的宏(Macro)属于编译器预处理的范畴,属于编译期概念(而非运行期概念).下面对常遇到的宏的使用问题做了简单总结. 关于#和## 在C语言的宏中,#的功能是将其后面的宏参数进行字符串化操作(Stringfication),简单说就是在对它所引用的宏变量 通过替换后在其左右各加上一个双引号.比如下面代码中的宏: #define WARN_IF(EXP) do{ if (EXP) fprintf(stderr, "Warning: " #EXP &quo

Java语言中的修饰符

类.方法.成员变量和局部变量的可用修饰符 修饰符 类 成员方法 构造方法 成员变量 局部变量 abstract Y Y _ _ _ static _ Y _ Y _ public Y Y Y Y _ protected _ Y Y Y _ private _ Y Y Y _ synchronized _ Y _ _ _ native _ Y _ _ _ transient _ _ _ Y _ volatile _ _ _ Y _ final Y Y _ Y Y 1.访问控制修饰符: Java语言

Java面向对象编程之Java语言中的修饰符

近日,读了孙卫琴老师的<Java面向对象编程>一书,心中颇有些感悟,想着将其记录下来. Java中的修饰符 在Java语言中,有这样一些单词(说得再准确点儿,应该是形容词):abstract(抽象的).static(静态的).public(公共的).protected(受保护的).private(私有的).synchronized(同步的).native(本地的).transient(暂时的).volatile(易失的)和final(不可改变的),它们被成为修饰符,这些修饰符可以修饰类.变量和

11 css中分组选择符的用法

<!doctype html> <html> <head> <meta charset="utf-8"> <title>无标题文档</title> <style type="text/css"> h1,span{color:red;} a:hover{color:#2EE926;} /*分组选择符的用法*/ </style> </head> <body&

关于Java语言中那些修饰符

一.在java中提供的一些修饰符,这些修饰符可以修饰类.变量和方法,在java中常见的修饰符有:abstract(抽象的).static(静态的).public(公共的).protected(受保护的).private(私有的).synchronized(同步的).native(本地的).transient(暂时的).volatile(易失的).final(不可改变的) 二.修饰顶层类的修饰符包括abstract.public和final,而static.protected和private不能修

C#语言中的修饰符汇总

1. 访问修饰符 指定声明的类型和类型成员的可访问性. (1) public:对任何类和成员都公开, 无限制访问;是类型和类型成员的访问修饰符.公共访问是允许的最高访问级别.对访问公共成员没有限制. (2) private:仅仅对该类公开;是一个成员访问修饰符.私有访问是允许的最低访问级别.私有成员只有在声明它们的类和结 构体中才是可访问的. (3) internal:只能值包含该类的程序集中访问该类(只是单独的项目,而不是整个解决方案);是类型和类型成员的访问修饰符.只有在同一程序集的文件中,