c语言中#和##的用法

c++ map用法_C语言中"##"的独特用法 来自公众号:裸机思维C语言中一个重要的内容,就是##的用法,可能绝大部分 C 程序员都不知道"##"隐藏用法,下面就来给大家讲讲。一、##的“表”用法想必很多人都知道"##"的用法——它本质上是一个“胶水运算”(连接字符串的作用),用于把参数宏中的“形参”与其它没有天然分割的内容粘连在一起,例如:#define def_u32_array(__name, __size) u... 阅读详情

转:https://www.cnblogs.com/lanjianhappy/p/7857757.html

原文有些错误,修正一下。


一、一般用法 
我们使用#把宏参数变为一个字符串,用##把两个宏参数贴合在一起. 
用法: 

#include<stdio.h> 
#include<limits.h> 

#define STR(s)     #s 
#define CONS(a,b)  (int)(a##e##b) 

int main() 
{ 
    printf(STR(vck));           // 输出字符串"vck" 
    printf("%d\n", CONS(2,3));  // 2e3 输出:2000   2e3是科学计数法  2 * 10 ^3
    return 0; 
} 

 

二、当宏参数是另一个宏的时候 
需要注意的是凡宏定义里有用'#'或'##'的地方宏参数是不会再展开. 

1, 非'#'和'##'的情况 

#define TOW      (2) 
#define MUL(a,b) (a*b) 

printf("%d*%d=%d\n", TOW, TOW, MUL(TOW,TOW)); 

这行的宏会被展开为: 
printf("%d*%d=%d\n", (2), (2), ((2)*(2))); 
MUL里的参数TOW会被展开为(2). 

2, 当有'#'或'##'的时候 

#define A          (2) 
#define STR(s)     #s 
#define CONS(a,b)  int(a##e##b) 
printf("int max: %s\n",  STR(INT_MAX));    // INT_MAX #include<limits.h> 

这行会被展开为: 
printf("int max: %s\n", "INT_MAX"); 

printf("%s\n", CONS(A, A));               // compile error  
这一行则是: 
printf("%s\n", int(AeA)); 

INT_MAX和A都不会再被展开, 然而解决这个问题的方法很简单. 加多一层中间转换宏. 
加这层宏的用意是把所有宏的参数在这层里全部展开, 那么在转换宏里的那一个宏(_STR)就能得到正确的宏参数. 

#define A         2    //此处2不能有()   
#define _STR(s)     #s 
#define STR(s)      _STR(s)          // 转换宏 
#define _CONS(a,b)  int(a##e##b) 
#define CONS(a,b)   _CONS(a,b)       // 转换宏 

printf("int max: %s\n", STR(INT_MAX));          // INT_MAX,int型的最大值,为一个变量 #include<limits.h> 

输出为: int max: 2147483647 
STR(INT_MAX) -->  _STR(2147483647) 然后再转换成字符串; 

printf("%d\n", CONS(A, A)); 
输出为:200 
CONS(A, A)  -->  _CONS(2, 2)  --> int(2e2) 

//#define A         2  //2左右不能加(),(2)e(2) 编译报错

三、'#'和'##'的一些应用特例 
1、合并匿名变量名 

#define  ___ANONYMOUS1(type, var, line)  type  var##line 
#define  __ANONYMOUS0(type, line)  ___ANONYMOUS1(type, _anonymous, line) 
#define  ANONYMOUS(type)  __ANONYMOUS0(type, __LINE__) 

例:ANONYMOUS(static int);  即: static int _anonymous70;  70表示该行行号; 
第一层:ANONYMOUS(static int);  -->  __ANONYMOUS0(static int, __LINE__); 
第二层:                        -->  ___ANONYMOUS1(static int, _anonymous, 70); 
第三层:                        -->  static int  _anonymous70; 
即每次只能解开当前层的宏,所以__LINE__在第二层才能被解开; 

2、填充结构 

#define  FILL(a)   {a, #a} 

enum IDD{OPEN, CLOSE}; 
typedef struct MSG{ 
  IDD id; 
  const char * msg; 
}MSG; 

MSG _msg[] = {FILL(OPEN), FILL(CLOSE)}; 

相当于: 

MSG _msg[] = {{OPEN, "OPEN"}, 
              {CLOSE, "CLOSE"}}; 

3、记录文件名 

#define  _GET_FILE_NAME(f)   #f 
#define  GET_FILE_NAME(f)    _GET_FILE_NAME(f) 
static char  FILE_NAME[] = GET_FILE_NAME(__FILE__); 

4、得到一个数值类型所对应的字符串缓冲大小 

#define  _TYPE_BUF_SIZE(type)  sizeof #type 
#define  TYPE_BUF_SIZE(type)   _TYPE_BUF_SIZE(type) 
char  buf[TYPE_BUF_SIZE(INT_MAX)]; 

     -->  char  buf[_TYPE_BUF_SIZE(2147483647)]; 
     -->  char  buf[sizeof("2147483647")]; 
这里相当于: 
char  buf[11];

小知识:C语言宏定义中 # 和 ## 符号的用法 在某些C语言代码中,有时我们可能会看到宏定义中带有#、##,这些符号有特殊的作用,下面我们用几个简单的例子来说明。 1)一个#的作用 一个#的作用就是把后面的参数当做一个字符串,也就是说等同于把后面的宏变量加上双引号: 运行上述代码,可以得到输出: Hello world 1 Hello world 2 说明 #define PRINT(NAME) printf(#NAME)这个宏,等同于把NAME加上了双引号“”,即替换成了“NAME”,所以,第一个PRINT可以直接把括号内的内容.. 阅读详情

相关推荐

c++中 # 和 ## 的用法总结

【代码】c++中 # 和 ## 的用法总结。

鸟哥的博客 1202

C语言中"##"的独特用法

关注、星标公众号,不错过精彩内容作者:傻孩子转自:裸机思维市面上有很多比较火的编程语言,比如Python、 JAVA、 Go等,你可能觉得C语言很古老、很落后。如果你有这种想法,那可能你...

strongerHuang 1万+

C语言中的预处理符号#和##的用法

综上所述,预处理符号#和##在C语言中具有重要的作用。#符号可用于将宏参数转换为字符串,而##符号可用于将两个标识符连接在一起。这些功能使得C语言的预处理器更加灵活和强大,为程序员提供了更多的提供了更多的编程技巧和工具。预处理器指令以井号(#)开头,其中包括了一些特殊符号,如#和##。这篇文章将详细介绍C语言中这两个符号的用法,并通过示例代码加以说明。在上面的代码中,我们定义了一个宏函数。在上面的代码中,我们定义了一个宏函数。,并使用#符号将其转换为字符串。,使用##符号将它们连接在一起。

带你成为别人眼中的大佬! 628

【C】 25_#和##操作符分析

#运算符 # 运算符用于在预处理期将宏参数转换为字符串 # 的转换作用是在预处理期完成的,因此只在宏定义中有效 编译器不知道 # 的转换作用 用法 #define STRING(x) #x printf("%s\n", STRING(Hello word)); 实例分析: #运算符的基本用法 #include <stdio....

weixin_34128501的博客 445

Unity 第一人称视角控制移动、旋转

第一人称视角操作此功能主要是借鉴YouTube,写的蛮好我就搬运过来让大家也试试。

qq_36515472的博客 4201

手势控制 Python !Leap Motion Python 开发教程 (二)

手势控制 Python !Leap Motion Python 开发教程 (二) 现在进入正题,我来给大家总结一下我在使用 Leap Motion 开发过程中的经验以及学到的东西,其中我会概括以及翻译官方给出的注释,为了让这些注释更加通俗易懂,让大家更好理解。 回顾 在上一篇文章中我们讲了如何配置 Leap Motion 的 Python 2.7 的开发环境,如果您还没有配置好您的开发环境,可以参...

成畅的博客 3191

c语言中_的用法,c语言中#和##的用法

本文主要讲述c语言的一点基础语法和在内核的应用中其中的一点例子。#,##分别在c语言中是怎么作用?文章代码编译的环境:桌面环境:Ubuntu10.04内核:linux2.6.32编译器:gcc4.4.3一、基本的用法1、#.参数名以#作为前缀则结果将被扩展为由实际参数的带引号的字符串。如:#define dprint(expr)printf(#expr"=%d\n",expr);intmain()...

weixin_35712223的博客 2270

AXI backpressure反压机制代码

本文将xilinx的axi读写代码进行修改,实现吞吐量达到50%

m0_64636251的博客 1764

C语言中 # 和##的用法

C语言中 ##用法

HardessGod的博客 8832

LatentSync:开源数字人唇形同步技术的实战部署与优化指南

本文详细介绍了开源数字人唇形同步工具LatentSync的实战部署与优化全流程。从核心原理(潜在扩散模型与TREPA技术)解析,到手把手完成环境搭建、模型获取及首次推理。文章深入探讨了自定义素材处理、关键参数调优(如guidance_scale),并提供了显存不足、人脸检测失败等常见问题的解决方案与性能优化技巧,旨在帮助用户高效部署并提升生成效果。

9o8p7i6u5y的博客 1004

esxi8.0.3如何添加USB外置硬盘

本文介绍了在ESXi系统中配置外置USB硬盘作为数据存储的完整步骤:1)通过SSH禁用USB仲裁服务并关闭自启;2)识别已连接的USB硬盘设备路径;3)使用partedUtil创建GPT分区表并计算扇区范围;4)设置VMFS6分区并格式化。关键命令包括停止usbarbitrator服务、partedUtil分区操作以及vmkfstools格式化命令。整个过程需通过SSH执行,最终将USB硬盘配置为名为"USB_Datastore"的VMFS6存储设备。

qq_41683719的博客 1544

C语言宏中“#”和“##”的用法

对于这两个语法的功能都比较简单,且都是在预处理阶段做一些工作 : #主要是将宏参数转化为字符串 ##主要是将两个标识符拼接成一个标识符

诊断协议那些事儿's blog 4711

华北理工大学以升实验班蓝桥杯选拔赛题解

文章目录华北理工大学以升实验班蓝桥杯选拔赛题解A:期末考试题目描述题目讲解代码B:月份题目描述题目讲解代码C:打饭题目描述题目讲解代码D : 正弦波信号题目描述题目讲解代码E : 亲爱的长方形题目描述题目讲解代码F:挖金子题目描述题目讲解代码G : 金金的游戏题目描述题目讲解代码H : 区间和题目描述题目讲解代码详细视频讲解请关注华北理工大学b站账号。 华北理工大学以升实验班蓝桥杯选拔赛题解 A:期末考试 题目描述 Description 期末考试过去许多天了,如今成绩都出来了,那么现在让我们对成绩我分个类

Qq1739206233的博客 1126

C语言中#和##用法

一、基本的用法 1、#——参数名以#作为前缀则结果将被扩展为由实际参数的带引号的字符串。 如: 1 2 3 4 5 6 7 8 #define dprint(expr)printf(#expr"=%d\n",expr); int main() {    int a=20,b=10

Ven_J的博客 835

Allegro层叠中的Etch Factor-铜皮的腐蚀因子如何计算

在用Allegro进行PCB设计的时候,Cross-section中需要填入对应的信息,一般填入每层的厚度即可,如下图。当PCB需要进行仿真分析的时候,Etch-Factor这个值是必须要填写的,如下图。实际铜皮进行蚀刻的时候,Etch-Factor的值并不是标准的90度,如下图。线路层实际形状是个梯形,Etch-Factor代表的就是梯形的角度,如下图。首先输入数值,比如1,再点击Inv,最后点击tan-1,可以得到角度的值。如果tanσ=2,σ=63.4,如下图计算结果。即tanσ=1,得到σ=45。

weixin_54787054的博客 884

Android 埋点信息分析——statsd框架

StatsPullAtomService 用以采集数据,并将数据填充到参数中,在StatsManager.PullAtomCallbackInternal 中会转换成 Parcel 格式传入到 native。 StatsCallbackPuller::PullInternal 中会回调StatsManager.PullAtomCallbackInternal 的onPullAtom,该函数中会回调StatsCallbackPuller::PullInternal 中定义的PullResultRecei

私房菜 2625

C 语言拾锦 —— ##和#预处理标记的用法及原理分析

先说结论:我们先来看一个例子,理解其第一点用法,并且熟悉下这种用法: 将其进行编译后,两个printf都会输出: 那么它具体是怎么实现的呢?其实很简单就是在其宏变量被替换,在其左右两侧加上双引号。为了探究这个过程,我们在用gcc编译的时候加上-E选项来看下编译器的预处理过程: 可以看到,gcc编译器的预处理过程和我们的猜想是一致的,预处理标记的作用确实只是在我们指定的参数两旁加上双引号使其成为一个字符串了。这里也可以看出预处理标记的工作原理了。可以看到上面的例子中没有换行,我们将其晚上一下。提供两种思路

wit_732的博客 2574

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

详解C语言中 # 和 ## 的用法

一句话总结功能: 使用#把宏参数变为一个字符串,用##把两个宏参数粘连到一起 ##用来连接前后两个参数,拼接符号。可以是符号拼符号,可以是数字拼符号,可以是数字拼数字 #用来对后面的宏参数进行字符串化操作,简单来说就是相当于在宏变量的两边各加上一个双引号使其变成一个字符串 注意,##和#只可用在宏定义中,这只是给编译器看的。(语句体中不可直接用##和#) 功能总结很简单,但实际应用方式却多种多样,可谓非常强大。 一、基础应用: 例1:使用 # ,把一个宏参数变成对应的字符串 #include<stdi

a只如初见的博客 1万+

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

[c语言]宏中 #和##的用法

在代码中,看到了包含##的宏。 例如:#define clear_opt(o, opt)       o &= ~EXT2_MOUNT_##opt 于是,一起看了下# 和 ##在宏中的用法。 wiki中的解释如下: # 为 字符串转换符, 将包含的字段转换为字符串。 ## 为 字段连接符,将两个字段 连接为 一个字段。 wiki的示例有一段示例比较有

sqk0315的博客 466

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

C语言宏中"#"和"##"的用法

C语言宏中"#"和"##"的用法    在查看linux内核源码的过程中,遇到了许多宏,这里面有许多都涉及到"#"和"##",因此,在网上搜索了一些资料,整理如下:一、一般用法 我们使用#把宏参数变为一个字符串,用##把两个宏参数贴合在一起. 用法: #include&lt;cstdio&gt; #include&lt;climits&gt; using namespace std; #d

weixin_34015860的博客 1488

C语言中##和#在宏定义中的用法

C语言的宏定义由于其特殊性具有特别高的可玩性,本篇文章介绍在宏定义中##和#的意义和用法。

m0_61195936的博客 418

C语言中“#“和“##“的用法

C语言中"#"和"##"的用法 1. 前言 使用#把宏参数变为一个字符串,用##把两个宏参数贴合在一起. 2. 一般用法 #include<cstdio> #include<climits> using namespace std; #define STR(s) #s #define CONS(a,b) int(a##e##b) int main() { printf(STR(vck)); // 输出字符串"vck" printf(

君君的博客 1万+

c语言中宏语句的格式和作用,C语言宏中"#"和"##"的用法

原标题:C语言宏中"#"和"##"的用法 C语言宏中"#"和"##"的用法在查看linux内核源码的过程中,遇到了许多宏,这里面有许多都涉及到"#"和"##",因此,在网上搜索了一些资料,整理如下:一般用法我们使用#把宏参数变为一个字符串,用##把两个宏参数贴合在一起.用法:#include#includeusing namespace std;#define STR(s) #s#define C...

weixin_39620118的博客 641
上一篇: 浅析C语言的一个关键字——register
下一篇: WebSocket 是什么原理?为什么可以实现持久连接?
evilcode
博客等级 码龄20年 307粉丝 16原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值