宏定义中##和#的作用

合集下载

define宏定义中的#,##,@#及符号

define宏定义中的#,##,@#及符号

d efine宏定义中的#,##,@#及\符号(ZT)C++ STL学习2011-04-24 18:04:03 阅读19 评论0 字号:大中小订阅1、# (stringizing)字符串化操作符。

其作用是:将宏定义中的传入参数名转换成用一对双引号括起来参数名字符串。

其只能用于有传入参数的宏定义中,且必须置于宏定义体中的参数名前。

如:#define example(instr) printf("the input string is:\t%s\n",#instr)#define example1(instr) #instr当使用该宏定义时:example(abc);在编译时将会展开成:printf("the input string is:\t%s\n","abc");string str=example1(abc);将会展成:string str="abc";注意:对空格的处理a。

忽略传入参数名前面和后面的空格。

如:str=example1( abc );将会被扩展成str="abc";b.当传入参数名间存在空格时,编译器将会自动连接各个子字符串,用每个子字符串中只以一个空格连接,忽略其中多余一个的空格。

如:str=exapme( abc def); 将会被扩展成str="abc def";2、## (token-pasting)符号连接操作符宏定义中:参数名,即为形参,如#define sum(a,b) (a+b);中a和b 均为某一参数的代表符号,即形式参数。

而##的作用则是将宏定义的多个形参成一个实际参数名。

如:#define exampleNum(n) num##nint num9=9;使用:int num=exampleNum(9); 将会扩展成int num=num9;注意:1.当用##连接形参时,##前后的空格可有可无。

c++define用法

c++define用法

c++define用法c++中define用法define在c++语言中用法比较多,这里对其进行整理。

1.无参宏定义无参宏的宏名后不带参数。

其定义的一般形式为:#define 标识符字符串其中的“#”表示这是一条预处理命令。

凡是以“#”开头的均为预处理命令。

“define”为宏定义命令。

“标识符”为所定义的宏名。

“字符串”可以是常数、表达式、格式串等。

例如:#define MAXNUM 99999这样MAXNUM就被简单的定义为99999。

2.有参宏定义C++语言允许宏带有参数。

在宏定义中的参数称为形式参数,在宏调用中的参数称为实际参数。

对带参数的宏,在调用中,不仅要宏展开,而且要用实参去代换形参。

带参宏定义的一般形式为:#define 宏名(形参表) 字符串在字符串中含有各个形参。

在使用时调用带参宏调用的一般形式为:宏名(实参表);例如:#define add(x, y) (x + y)int main(){cout << "1 plus 1 is " << add(1, 1.5) << ".\n";system("pause");return(0);}这个“函数”定义了加法,但是该“函数”没有类型检查,有点类似模板,但没有模板安全,可以看做一个简单的模板。

注意:该“函数”定义为(a + b),在这里加括号的原因是,宏定义只是在预处理阶段做了简单的替换,如果单纯的替换为a + b时,当你使用5 * add(2, 3)时,被替换为5 * 2 + 3,值为13,而非5 * (2 + 3),值为25。

3.宏定义中的特殊操作符define 中的特殊操作符有#,##和… and __VA_ARGS__ (1)#假如希望在字符串中包含宏参数,ANSI C允许这样作,在类函数宏的替换部分,#符号用作一个预处理运算符,它可以把语言符号转化程字符串。

C语言中的宏定义用法

C语言中的宏定义用法

C语言中的宏定义用法宏定义是C语言中一种重要的预处理指令,通过宏定义可以为一些常用的代码片段或数值指定名称,方便程序开发和维护。

本文将介绍C语言中宏定义的用法和注意事项。

首先,在C语言中,宏定义使用“#define”关键字进行定义,其语法格式为:```#define 宏名称值```其中,宏名称是自定义的标识符,可以是任意有效的变量名或符号;值可以是任意的表达式、常量或代码片段。

通过宏定义,我们可以将一些重复使用的代码片段定义为宏,以提高代码的重用性和可读性。

在使用宏定义时,需要注意以下几点:1. 宏定义不需要分号结尾,直接写在宏定义行即可。

2. 宏名称一般使用大写字母表示,以区分于普通变量。

3. 宏定义的值可以是任意合法的C语句,但最好使用括号将其括起来,防止优先级问题。

4. 宏定义中可以使用参数,以实现不同场景下的值替换。

除了定义普通的宏之外,C语言中还有一种特殊的宏定义“#define MAX(a, b) ((a) > (b) ? (a) : (b))”,这种宏定义被称为宏函数,可以实现简单的函数功能。

宏函数通常使用括号将参数括起来,以确保表达式的正确性。

另外,C语言中还有一些系统预定义的宏,如“__FILE__”表示当前文件名,“__LINE__”表示当前行号,“__FUNCTION__”表示当前函数名等。

这些宏可以在调试和错误提示时起到一定的作用,方便程序员定位问题。

在使用宏定义时,需要注意一些潜在的问题,如:1. 宏定义的替换是简单的文本替换,可能会产生一些意外的结果。

2. 宏定义带来的代码重复可能会增加代码的长度,降低代码的可读性。

3. 在调试时,宏定义会隐藏实际代码逻辑,导致调试困难。

综上所述,C语言中的宏定义是一种方便而强大的工具,可以提高代码的可维护性和可读性。

在使用宏定义时,需要注意语法规范和潜在的问题,以充分发挥其优势。

通过合理地运用宏定义,可以使程序更加简洁高效,提升开发效率。

宏定义中##和#的作用

宏定义中##和#的作用
例如:
> #define STRCPY(dst, src) strcpy(dst, #src)

> STRCPY(buff, abc)
相当于strcpy(buff, "abc")
另外,如果##后的参数本身也是一个宏的话,##会阻止这个宏的展开。
#define STRCPY(a, b) s源自rcpy(a ## _p, #b)
__attribute__ ((unused, alias(__stringify(name))))
得到
MODULE_DEVICE_TABLE(usb, products)
/*notes: struct usb_device_id products; */
<==> MODULE_GENERIC_TABLE(usb_device,products)
另外一些分隔标志是,包括操作符,比如+, -, *, /, [,], ...,所以尽管下面的
宏定义没有空格,但是依然表达有意义的定义:define add(a, b) a+b
而其强制连接的作用是,去掉和前面的字符串之间的空格,而把两者连接起来。
2.举列--试比较下述几个宏定义的区别
#define A1(name, type) type name_##type##_type或
<==> extern const struct usb_device_id __mod_usb_device_table
__attribute__ ((unused, alias("products")))
注意到alias attribute需要一个双引号,所以在这里使用了__stringify(name)来

C语言中的宏定义

C语言中的宏定义

C语言中的宏定义(全面整编) 目录1. 简单宏定义2. 带参数的宏3. 运算符4. 运算符5. 宏的通用属性6. 宏定义中圆括号7. 创建较长的宏1. 较长的宏中的逗号运算符2. 宏定义中的do-while循环do3. 空操作的定义8. 预定义宏9. C语言中常用的宏1. 简单宏定义简单的宏定义有如下格式:[#define指令(简单的宏)] #define 标识符替换列表替换列表是一系列的C语言记号,包括标识符、关键字、数、字符常量、字符串字面量、运算符和标点符号。

当预处理器遇到一个宏定义时,会做一个“标识符”代表“替换列表”的记录。

在文件后面的内容中,不管标识符在任何位置出现,预处理器都会用替换列表代替它。

不要在宏定义中放置任何额外的符号,否则它们会被作为替换列表的一部分。

一种常见的错误是在宏定义中使用 = :#define N = 100 /*** WRONG ***/int a[N]; /* 会成为 int a[= 100]; */在上面的例子中,我们(错误地)把N定义成一对记号(= 和100)。

在宏定义的末尾使用分号结尾是另一个常见错误:#define N 100; /*** WRONG ***/int a[N]; /* become int a[100;]; */这里N被定义为100和;两个记号。

在一个宏定义中,编译器可以检测到绝大多数由多余符号所导致的错误。

但不幸的是,编译器会将每一处使用这个宏的地方标为错误,而不会直接找到错误的根源——宏定义本身,因为宏定义已经被预处理器删除了。

简单的宏主要用来定义那些被Kernighan和Ritchie称为“明示常量”(manifest constant)的东西。

使用宏,我们可以给数值、字符和字符串命名。

#define STE_LEN 80#define TRUE 1#define FALSE 0#define PI 3.14159#define CR '\r'#define EOS '\0'使用#define来为常量命名有许多显著的优点:1) 程序会更易读。

c语言def用法

c语言def用法

C语言def用法在C语言中,def是一个关键字,用于定义宏。

宏是一种预处理指令,用于在程序编译之前进行文本替换。

使用宏可以简化代码,提高代码的可读性和可维护性。

宏的定义和使用宏的定义使用#define关键字,语法如下:#define 宏名替换文本宏名是一个标识符,替换文本可以是任意合法的C语言表达式。

宏的使用是通过在代码中使用宏名来实现的。

在编译时,预处理器会将宏名替换为对应的替换文本。

下面是一个简单的宏定义和使用的例子:#include <stdio.h>#define PI 3.14159int main() {double radius = 5.0;double area = PI * radius * radius;printf("The area of a circle with radius %.2f is %.2f\n", radius, area);return 0;}在上面的例子中,#define PI 3.14159定义了一个名为PI的宏,它的替换文本是3.14159。

在main()函数中,通过使用PI来计算圆的面积。

宏的参数宏可以带有参数,使得宏的替换文本可以根据不同的参数值进行变化。

宏参数的语法类似于函数的参数,可以在宏定义中使用。

下面是一个带有参数的宏定义和使用的例子:#include <stdio.h>#define SQUARE(x) ((x) * (x))int main() {int num = 5;int square = SQUARE(num);printf("The square of %d is %d\n", num, square);return 0;}在上面的例子中,#define SQUARE(x) ((x) * (x))定义了一个名为SQUARE的宏,它带有一个参数x。

宏的替换文本是(x) * (x),即参数x的平方。

arm中的宏定义

arm中的宏定义

arm中的宏定义
语法格式如下:MACRO [$ label] macroname{ $ parameter1,$ parameter,} 其他指令MEND MACRO 伪操作标识宏定义的开始,MEND 标
识宏定义的结束。

用MACRO 及MEND 定义一段代码,称为宏定义体,这样
在程序中就可以通过宏指令多次调用该代码段。

其中,$ label 在宏指令被展
开时,label 会被替换成相应的符号,通常是一个标号。

宏定义中的$label 是一
个可选参数,在一个符号前使用$表示程序被汇编时将使用相应的值来替代$后
的符号。

macroname 为所定义的宏的名称。

$parameter 为宏指令的参数。

当宏指令被展开时将被替换成相应的值,类似于函数中的形式参数,可以在宏定
义时为参数指定相应的默认值。

例如:
定义宏如下:
MACRO
$label TestBranch$dest, $reg, $cc
$label
CMP $reg,#0
B$cc $dest
MEND
调用宏的过程如下:
testTestBranch Nonzero,r0, NE
Nonzero
............
程序汇编后,宏展开如下:。

C++ 宏定义中字符串连接操作详解

C++ 宏定义中字符串连接操作详解

关于记号粘贴操作符(token paste operator): ##1. 简单的说,“##”是一种分隔连接方式,它的作用是先分隔,然后进行强制连接。

其中,分隔的作用类似于空格。

我们知道在普通的宏定义中,预处理器一般把空格解释成分段标志,对于每一段和前面比较,相同的就被替换。

但是这样做的结果是,被替换段之间存在一些空格。

如果我们不希望出现这些空格,就可以通过添加一些##来替代空格。

另外一些分隔标志是,包括操作符,比如 +, -, *, /, [,], …,所以尽管下面的宏定义没有空格,但是依然表达有意义的定义: define add(a, b) a+b而其强制连接的作用是,去掉和前面的字符串之间的空格,而把两者连接起来。

2. 举列–试比较下述几个宏定义的区别#define A1(name, type) type name_##type##_type 或#define A2(name, type) type name##_##type##_typeA1(a1, int); /* 等价于: int name_int_type; */A2(a1, int); /* 等价于: int a1_int_type; */解释:1) 在第一个宏定义中,”name”和第一个”_”之间,以及第2个”_”和第二个”type”之间没有被分隔,所以预处理器会把name_##type##_type解释成3段:“name_”、“type”、以及“_type”,这中间只有“type”是在宏前面出现过的,所以它可以被宏替换。

2) 而在第二个宏定义中,“name”和第一个“_”之间也被分隔了,所以预处理器会把name##_##type##_type解释成4段:“name”、“_”、“type”以及“_type”,这其间,就有两个可以被宏替换了。

3) A1和A2的定义也可以如下:#define A1(name, type) type name_ ##type ##_type<##前面随意加上一些空格>#define A2(name, type) type name ##_ ##type ##_type 结果是## 会把前面的空格去掉完成强连接,得到和上面结果相同的宏定义3. 其他相关–单独的一个 #至于单独一个#,则表示对这个变量替换后,再加双引号引起来。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

宏定义中##和#的作用
————————————————————————————————作者: ————————————————————————————————日期:

内核中有很多的宏定义,在宏定义define中经常看到两个字符串##和#,这里把它的用法做一下说明:
##是一个连接符号,用于把参数连在一起
例如:
>#define FOO(arg) my##arg

> FOO(abc)
相当于myabc
#是“字符串化”的意思。

出现在宏定义中的#是把跟在后面的参数转换成一个字符串例如:
> #defineSTRCPY(dst,src)strcpy(dst,#src)

>STRCPY(buff, abc)
相当于strcpy(buff, "abc")
另外,如果##后的参数本身也是一个宏的话,##会阻止这个宏的展开。

#define STRCPY(a, b)strcpy(a##_p, #b)
int main()
{
char var1_p[20];
charvar2_p[30];
strcpy(var1_p,"aaaa");
strcpy(var2_p, "bbbb");
STRCPY(var1,var2);
STRCPY(var2, var1);
printf("var1= %s\n", var1_p);
printf("var2= %s\n", var2_p);
return 0;
/*注意这里*/
STRCPY(STRCPY(var1,var2),var2);
/*这里是否会展开为:strcpy(strcpy(var1_p,"var2")_p,"var2“)?
* 答案是否定的:
* 展开结果将是:strcpy(STRCPY(var1,var2)_p,"var2")
*## 阻止了参数的宏展开!
*如果宏定义里没有用到#和##, 宏将会完全展开
*/
}
/////////////////////////////////////////////////////////////////////////
tell youabout ## incommon text
关于记号粘贴操作符(token pasteoperator):##
1.简单的说,“##”是一种分隔连接方式,它的作用是先分隔,然后进行强制连接。

其中,分隔的作用类似于空格。

我们知道在普通的宏定义中,预处理器一般把空格解释成分段标志,对于每一段和前面比较,相同的就被替换。

但是这样做的结果是, 被替换段之间存在一些空格。

如果我们不希望出现这些空格,就可以通过添加一些
##来替代空格。

另外一些分隔标志是,包括操作符,比如+, -, *, /,[,], ...,所以尽管下面的
宏定义没有空格,但是依然表达有意义的定义: define add(a, b)a+b
而其强制连接的作用是,去掉和前面的字符串之间的空格,而把两者连接起来。

2.举列-- 试比较下述几个宏定义的区别
#define A1(name, type) type name_##type##_type 或
#define A2(name,type)typename##_##type##_type
A1(a1,int); /*等价于: int name_int_type; */
A2(a1, int); /*等价于: int a1_int_type;*/
解释:
1)在第一个宏定义中,"name"和第一个"_"之间,以及第2个"_"和第二个
"type"之间没有被分隔,所以预处理器会把name_##type##_type解释成3段: “name_”、“type”、以及“_type”,这中间只有“type”是在宏前面出现过
的,所以它可以被宏替换。

2) 而在第二个宏定义中,“name”和第一个“_”之间也被分隔了,所以
预处理器会把name##_##type##_type解释成4段:“name”、“_”、“type”
以及“_type”,这其间,就有两个可以被宏替换了。

3) A1和A2的定义也可以如下:
#defineA1(name,type) type name_##type ##_type
<##前面随意加上一些空格> #define A2(name,type)type name ##_##type ##_type
结果是## 会把前面的空格去掉完成强连接,得到和上面结果相同的宏定义
3.其他相关--单独的一个#
至于单独一个#,则表示对这个变量替换后,再加双引号引起来。

比如
#define__stringify_1(x) #x
那么
__stringify_1(linux)<==> "linux"
所以,对于MODULE_DEVICE_TABLE
1) #define MODULE_DEVICE_TABLE(type,name)
MODULE_GENERIC_TABLE(type##_device,name)
2) #define MODULE_GENERIC_TABLE(gtype,name)
extern conststruct gtype##_id __mod_##gtype##_table
__attribute__((unused, alias(__stringify(name))))
得到
MODULE_DEVICE_TABLE(usb, products)
/*notes: struct usb_device_id product s; */
<==> MODULE_GENERIC_TABLE(usb_device,products)
<==> extern const structusb_device_id __mod_usb_device_table
__attribute__ ((unused, alias("products")))
注意到alias attribute需要一个双引号,所以在这里使用了__stringify(name)来
给name加上双引号。

另外,还注意到一个外部变量"__mod_usb_device_table"被alias 到了本驱动专用的由用户自定义的变量products<usb_device_id类型>。

这个外部变量是如何使用的,更多的信息请参看《probe()过程分析》。

4. 分析方法和验证方式--编写一个简单的C程序
用宏定义一个变量,同时用直接方式定义一个相同的变量,编译报告重复定义;
用宏定义一个变量,直接使用该宏定义的变量名称,编译通过且运行结果正确;
使用printf打印字符串数据。

printf("token macro is%s",__stringify_1(a1));。

相关文档
最新文档