文档库 最新最全的文档下载
当前位置:文档库 › 宏定义中#等的用法

宏定义中#等的用法

宏定义中#等的用法
宏定义中#等的用法

C语言宏定义中"#","#@"和"##"的用法一、引言

#define macro(a)#a

#define macro2(a,b)a##b

#define macro3(a,b,c)a##b##c

#a,表示a不再是一个变量,而变成了字符串"a"

##表示连接,a##b,表示输入的参数名为ab,a##b##c同理,代表变量名为:abc

测试例子:

int x=3;

int y=4;

int xy=10;

int xyz=20;

CString str;

OutputDebugString(macro(x));

str.Format("%d",macro2(x,y));

OutputDebugString(str);

str.Format("%d",macro3(x,y,z));

OutputDebugString(str);

输出结果为:

x

10

20

第一个为x,marco(x),x变成了"x"字符串

第二个为10,macro(x,y),就是变量xy

第三个为20,macro(x,y,z),就是变量xyz

二、一般用法

#把宏参数变为一个字符串,#@把宏参数变为一个字符,##把两个宏参数贴合在一起。

#include

#include

#define STR(s)#s//#与参数之间可以有空格

#define TOCHAR(c)#@c

#define CONS(a,b)int(a##e##b)//##与参数之间可以有空格

int main(void)

{

printf(STR(pele));//输出字符串"pele"

printf("%c\n",TOCHAR(z));//输出字符z

printf("%d\n",CONS(2,3));//2e3输出:2000

return0;

}

三、当宏参数是另一个宏的时候

需要注意的是凡宏定义里有用'#'或'##'的地方宏参数是不会再展开的。

#define A(2)

#define STR(s)#s

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

printf("int max:%s\n",STR(INT_MAX));

这行会被展开为:

printf("int max:%s\n","INT_MAX");

printf("%s\n",CONS(A,A));

这一行被展开为:

printf("%s\n",int(AeA));

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

#define A(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:0x7fffffff

STR(INT_MAX)-->_STR(0x7fffffff)-->"0x7fffffff"

printf("%d\n",CONS(A,A));

输出为:200

CONS(A,A)-->_CONS((2),(2))-->int((2)e(2))

以下为Minix3操作系统相关的源代码:

#ifdef_ANSI

#define__str(x)#x

#define__xstr(x)__str(x)//转换宏

_PROTOTYPE(void__bad_assertion,(const char*_mess));

#define assert(expr)((expr)?(void)0:\

__bad_assertion("Assertion\""#expr\

"\"failed,file"__xstr(__FILE__)\

",line"__xstr(__LINE__)"\n"))

四、"#"和"##"的一些应用特例

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(0x7fffffff)];

-->char buf[sizeof"0x7fffffff"];

这里相当于:

char buf[11];

五、C/C++宏定义的可变参数

编写代码的过程中,经常会输出一些调试信息到屏幕上,一般会调用printf这类的函数。

但是当调试解决之后,我们需要手工将这些地方删除或者注释掉。

再这次的项目中就用到类似问题,为了调试程序,再一些地方输出了很多的信息,随着项目的调试,输出的信息越来越多。于是就面临着,如何处理这些输出信息的语句。

简单删掉,不仅有一定的工作量,而且也不能保证之后就不出现问题,出现问题后这些信息还是有用的。

不去掉,带着调试信息就上线,这是明显不允许的。

于是就想到了一个可行的办法。如下:

void myprintf(char*fmt,...)

{

}

#ifdef DEBUG

#define printf(fmt,args...)myprintf(fmt,##args)

#endif

调试阶段带着DEBUG调试,正式上线就可以把printf变成一个空函数了。

这样做的一个潜在风险是可能会导致默写glib函数需要调用printf输出错误log也给取

消掉了。

令人欣慰的是,大部分glib调用的应该是fprintf。

虽然问题解决了,但是我对args...以及##args还是不太了解。上网找了些gcc手册的资料如下:

带有可变参数的宏(Macros with a Variable Number of Arguments)

在1999年版本的ISO C标准中,宏可以象函数一样,定义时可以带有可变参数。宏的语法和函数的语法类似。下面有个例子:

#define debug(format,...)fprintf(stderr,format,__VA_ARGS__)

这里,‘…’指可变参数。这类宏在被调用时,它(这里指‘…’)被表示成零个或多个符号,包括里面的逗号,一直到到右括弧结束为止。当被调用时,在宏体(macro body)中,那些符号序列集合将代替里面的__VA_ARGS__标识符。更多的信息可以参考CPP手册。

GCC始终支持复杂的宏,它使用一种不同的语法从而可以使你可以给可变参数一个名字,如同其它参数一样。例如下面的例子:

#define debug(format,args...)fprintf(stderr,format,args)

这和上面举的那个ISO C定义的宏例子是完全一样的,但是这么写可读性更强并且更容易进行描述。

GNU CPP还有两种更复杂的宏扩展,支持上面两种格式的定义格式。

在标准C里,你不能省略可变参数,但是你却可以给它传递一个空的参数。例如,下面的宏调用在ISO C里是非法的,因为字符串后面没有逗号:

debug("A message")

GNU CPP在这种情况下可以让你完全的忽略可变参数。在上面的例子中,编译器仍然会有问题(complain),因为宏展开后,里面的字符串后面会有个多余的逗号。

为了解决这个问题,CPP使用一个特殊的‘##’操作。书写格式为:

#define debug(format,...)fprintf(stderr,format,##__VA_ARGS__)

这里,如果可变参数被忽略或为空,‘##’操作将使预处理器(preprocessor)去除掉它前面的那个逗号。如果你在宏调用时,确实提供了一些可变参数,GNU CPP也会工作正常,它会把这些可变参数放到逗号的后面。象其它的pasted macro参数一样,这些参数不是宏的扩展。

参考资料:

[1]https://www.wendangku.net/doc/3313851084.html,/s/blog_550405a10100bqar.html

[2]Minix操作系统内核代码

宏定义的作用

宏定义的作用 宏定义是C提供的三种预处理功能的其中一种,这三种预处理包括:宏定义、文件包含、 条件编译 编辑本段1.不带参数的宏定义: 宏定义又称为宏代换、宏替换,简称“宏”。 格式: #define 标识符字符串 其中的标识符就是所谓的符号常量,也称为“宏名”。 预处理(预编译)工作也叫做宏展开:将宏名替换为字符串。 掌握"宏"概念的关键是“换”。一切以换为前提、做任何事情之前先要换,准确理解之前就要 “换”。 即在对相关命令或语句的含义和功能作具体分析之前就要换: 例: #define PI 3.1415926 把程序中出现的PI全部换成3.1415926 说明: (1)宏名一般用大写 (2)使用宏可提高程序的通用性和易读性,减少不一致性,减少输入错误和便于修改。例 如:数组大小常用宏定义 (3)预处理是在编译之前的处理,而编译工作的任务之一就是语法检查,预处理不做语法 检查。 (4)宏定义末尾不加分号; (5)宏定义写在函数的花括号外边,作用域为其后的程序,通常在文件的最开头。 (6)可以用#undef命令终止宏定义的作用域 (7)宏定义可以嵌套 (8)字符串" "中永远不包含宏 (9)宏定义不分配内存,变量定义分配内存。 编辑本段2.带参数的宏定义: 除了一般的字符串替换,还要做参数代换 格式: #define 宏名(参数表)字符串 例如:#define S(a,b) a*b area=S(3,2);第一步被换为area=a*b; ,第二步被换为area=3*2; 类似于函数调用,有一个哑实结合的过程: (1)实参如果是表达式容易出问题 #define S(r) r*r area=S(a+b);第一步换为area=r*r;,第二步被换为area=a+b*a+b; 正确的宏定义是#define S(r) ((r)*(r)) (2)宏名和参数的括号间不能有空格 (3)宏替换只作替换,不做计算,不做表达式求解 (4)函数调用在编译后程序运行时进行,并且分配内存。宏替换在编译前进行,不分配内 存 (5)宏的哑实结合不存在类型,也没有类型转换。

第十五讲 宏定义

第十五讲宏定义、文件包含和条件编译 ?C语言提供的预处理功能主要有三种: 宏定义 文件包含 条件编译 ?为了区别预处理命令和C语句、定义和说明语句,规定: 预处理命令行必须在一行的开头; 必须以#开始; 每行末尾不能加分号。 1、宏定义 宏定义 1.1不带参数的宏定义 不带参数的宏定义命令形式为: #define 宏名字符串 或#define 宏名 #define的作用是用指定的标识符(宏名)来代表字符串。其中#define是宏定义命令,宏名是一个标识符。 【例】输入一个圆的半径,计算并输出圆的面积和周长 #define PI 3.14159 main( ) {float l,s,r; /*l:周长,s:面积,r:半径*/ printf("Please input radius: "); scanf("%f",&r); /*输入半径*/ l=2.0*r*PI; /*计算周长*/ s=PI*r*r; /*计算面积*/ printf("l=%10.4f\ns=%10.4f\n",l,s); } 说明: 为了与变量名区别,建议宏名一般用大写字母。使用宏名代替一个 字符串,目的一是减少程序中某些重复使用字符串的书写量,其二 是增加程序的可读性。在编译预处理过程中会进行宏展开。 当宏定义在一行中写不下,需要在下一行继续时,只需在最后一个 字符后紧接一个反斜线“\”。注意在第二行开始不要有空格,否则空 格会一起被替换。 例如:#define LEAP_YEAR year % 4==0\ && year %100!=0 || year % 400==0 在C语言中,宏定义一般写在程序开头。宏名的有效范围为定义命 令之后到本源文件结束,除非用#undef命令终止宏名的作用域。 对程序中用双引号括起来的字符串内的子串和用户标识符中的成分 不做替换。例如已定义: 同一个宏名不能重复定义,除非两个宏定义命令行完全一致。 1.2带参数的宏定义 形参表中的不同形参之间用逗号隔开,字符串中包含形参表中的参数,带参

C语言宏定义#define

C语言宏定义#define 一、数值宏常量 #define 宏定义是个演技非常高超的替身演员,但也会经常耍大牌的,所以我们用它要慎之又慎。它可以出现在代码的任何地方,从本行宏定义开始,以后的代码就就都认识这个宏了;也可以把任何东西定义成宏。因为编译器会在预编译的时候用真身替换替身,而在我们的代码里面却又用常常用替身来帮忙。看例子: #define PI 3.141592654 在此后的代码中你尽可以使用PI 来代替3.141592654,而且你最好就这么做。不然的话,如果我要把PI 的精度再提高一些,你是否愿意一个一个的去修改这串数呢?你能保证不漏不出错?而使用PI 的话,我们却只需要修改一次。这种情况还不是最要命的,我们再看一个例子: #define ERROR_POWEROFF -1 如果你在代码里不用ERROR_POWEROFF 这个宏而用-1,尤其在函数返回错误代码的时候(往往一个开发一个系统需要定义很多错误代码)。肯怕上帝都无法知道-1 表示的是什么意思吧。这个-1,我们一般称为“魔鬼数”,上帝遇到它也会发狂的。所以,我奉劝你代码里一定不要出现“魔鬼数”。 第一章我们详细讨论了const 这个关键字,我们知道const 修饰的数据是有类型的,而define 宏定义的数据没有类型。为了安全,我建议你以后在定义一些宏常数的时候用const代替,编译器会给const 修饰的只读变量做类型校验,减少错误的可能。但一定要注意const修饰的不是常量而是readonly 的变量,const 修饰的只读变量不能用来作为定义数组的维数,也不能放在case 关键字后面。 二、字符串宏常量 除了定义宏常数之外,经常还用来定义字符串,尤其是路径: A),#define ENG_PA TH_1 E:\English\listen_to_this\listen_to_this_3 B),#define ENG_PATH_2 “E:\English\listen_to_this\listen_to_this_3” 噢,到底哪一个正确呢?如果路径太长,一行写下来比较别扭怎么办?用反斜杠接续符啊:C), #define ENG_PA TH_3 E:\English\listen_to_this\listen\_to_this_3 还没发现问题?这里用了4 个反斜杠,到底哪个是接续符?回去看看接续符反斜杠。 反斜杠作为接续符时,在本行其后面不能再有任何字符,空格都不行。所以,只有最后一个反斜杠才是接续符。至于A)和B),那要看你怎么用了,既然define 宏只是简单的替换,那给ENG_PATH_1 加上双引号不就成了:“ENG_PA TH_1”。 但是请注意:有的系统里规定路径的要用双反斜杠“\\”,比如: #define ENG_PATH_4 E:\\English\\listen_to_this\\listen_to_this_3 三、用define 宏定义注释符号? 上面对define 的使用都很简单,再看看下面的例子: #define BSC // #define BMC /*

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##n int num9=9; 使用: int num=exampleNum(9); 将会扩展成int num=num9; 注意: 1.当用##连接形参时,##前后的空格可有可无。 如:#define exampleNum(n) num ## n 相当于#define exampleNum(n) num##n 2.连接后的实际参数名,必须为实际存在的参数名或是编译器已知的宏定义 // preprocessor_token_pasting.cpp

Excel宏函数

Excel宏函数 [ 2011-02-28 14:27:55 ] 标签:无阅读对象:所有人 Microsoft Excel是一个多功能的电子表格应用程序,组织成列和行的数据多种形式。该方案还提供了分析数据的功能强大的设置后,输入。在单元公式以及菜单选项可以很容易地进行计算,排序和电子表格上的资料相符。在该计划的最强大的能力是可以选择建立的宏。这些都是在Excel中设计使用Visual Basic(V BA)的语言课程。 VBA函数构成任何Excel宏的基石。 数值函数 许多用户在Excel依靠其庞大的数学函数库。宏程序员可以利用数值函数的VBA 进行舍入和截断等共同任务。函数“回合”允许一个宏程序简单一轮任何一个E xcel网格数目增加或减少某一特定小数位。如果一个数的功能部分应该被忽略,而不是完全删除,在“诠释”功能截断的数字。三角函数,如“仙”,“余弦”和“谈”使人们有可能创造在一个宏观的几何计算。一个数字的绝对值可以来自于“绝对”的功能。这些共同的数学函数很容易集成到任何Excel宏为任何应用数值计算。 财政职能 Microsoft Excel是由于其之间的财务职能的扩展库金融专业人士的欢迎。它可以使用在Excel宏这些函数来创建快捷和方便的金融计算器。函数“何首乌”计算的贷款金额在其本金,利息率和付款时间表的基础。类似的是“Ipmt”功能,它使用相同的参数只返回一个贷款支付的利息部分。函数“NPER函数”可以确定所需的款项总数还清给予其主要价值,利率和偿还贷款的安排。的“抗体”的功能决定了未来的投资价值相同的变量为基础。这些功能可以快速生成复杂的公式,没有建设手动有用的财务数据。 文本函数 虽然Excel是一个用于操作数字数据的好工具,它也提供了字符串函数处理文本

宏定义中##和#的作用

宏定义中##和#的作用

————————————————————————————————作者: ————————————————————————————————日期: ?

内核中有很多的宏定义,在宏定义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") *## 阻止了参数的宏展开! *如果宏定义里没有用到#和##, 宏将会完全展开 */ } /////////////////////////////////////////////////////////////////////////

宏定义中#等的用法

C语言宏定义中"#","#@"和"##"的用法一、引言 #define macro(a)#a #define macro2(a,b)a##b #define macro3(a,b,c)a##b##c #a,表示a不再是一个变量,而变成了字符串"a" ##表示连接,a##b,表示输入的参数名为ab,a##b##c同理,代表变量名为:abc 测试例子: int x=3; int y=4; int xy=10; int xyz=20; CString str; OutputDebugString(macro(x)); str.Format("%d",macro2(x,y)); OutputDebugString(str); str.Format("%d",macro3(x,y,z)); OutputDebugString(str); 输出结果为: x 10 20 第一个为x,marco(x),x变成了"x"字符串 第二个为10,macro(x,y),就是变量xy 第三个为20,macro(x,y,z),就是变量xyz 二、一般用法 #把宏参数变为一个字符串,#@把宏参数变为一个字符,##把两个宏参数贴合在一起。

#include #include #define STR(s)#s//#与参数之间可以有空格 #define TOCHAR(c)#@c #define CONS(a,b)int(a##e##b)//##与参数之间可以有空格 int main(void) { printf(STR(pele));//输出字符串"pele" printf("%c\n",TOCHAR(z));//输出字符z printf("%d\n",CONS(2,3));//2e3输出:2000 return0; } 三、当宏参数是另一个宏的时候 需要注意的是凡宏定义里有用'#'或'##'的地方宏参数是不会再展开的。 #define A(2) #define STR(s)#s #define CONS(a,b)int(a##e##b) printf("int max:%s\n",STR(INT_MAX)); 这行会被展开为: printf("int max:%s\n","INT_MAX"); printf("%s\n",CONS(A,A)); 这一行被展开为: printf("%s\n",int(AeA)); INT_MAX和A都不会再被展开,然而解决这个问题的方法很简单,多加一层中间转换宏。加这层宏的用意是把所有宏的参数在这层里全部展开,那么在转换宏里的那一个宏(_STR)就能得到正确的宏参数。 #define A(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:0x7fffffff STR(INT_MAX)-->_STR(0x7fffffff)-->"0x7fffffff"

C宏定义

C/C++中宏使用总结 .C/C++中宏总结C程序的源代码中可包括各种编译指令,这些指令称为预处理命令。虽然它们实际上不是C语言的一部分,但却扩展了C程 序设计的环境。本节将介绍如何应用预处理程序和注释简化程序开发过程,并提高程序的可读性。ANSI标准定义的C语言预处理程序包括下列命令: #define,#error,#i nclude,#if,#else,#elif,#endif,#ifdef,#ifndef,#undef,#line,#pragma等。非常明显,所有预处理命令均以符号#开头,下面分别加以介绍。 1、#define 命令#define定义了一个标识符及一个串。在源程序中每次遇到该标识符时,均以定义的串代换它。ANSI标准将标识符定义为宏名,将替换过程称为宏 替换。命令的一般形式为: #define identifier string 注意: ? 该语句没有分号。在标识符和串之间可以有任意个空格,串一旦开始,仅由一新行结束。 ? 宏名定义后,即可成为其它宏名定义中的一部分。 ? 宏替换仅仅是以文本串代替宏标识符,前提是宏标识符必须独立的识别出来,否则不进行替换。例如:#define XYZ this is a test,使用宏printf("XYZ");//该段不打印"this is a test"而打印"XYZ"。因为预编译器识 别出的是"XYZ" ? 如果串长于一行,可以在该行末尾用一反斜杠' \'续行。

2、#error 处理器命令#error强迫编译程序停止编译,主要用于程序调试。 3、#i nclude 命令#i nclude使编译程序将另一源文件嵌入带有#i nclude的源文件,被读入的源文件必须用双引号或尖括号括起来。例如: #i nclude"stdio.h"或者#i nclude 这两行代码均使用C编译程序读入并编译用于处理磁盘文件库的子程序。 将文件嵌入#i nclude命令中的文件内是可行的,这种方式称为嵌套的嵌入文件,嵌套层次依赖于具体实现。 如果显式路径名为文件标识符的一部分,则仅在哪些子目录中搜索被嵌入文件。否则,如果文件名用双引号括起来,则首先检索当前工作目录。如果未发现文件, 则在命令行中说明的所有目录中搜索。如果仍未发现文件,则搜索实现时定义的标准目录。 如果没有显式路径名且文件名被尖括号括起来,则首先在编译命令行中的目录内检索。 如果文件没找到,则检索标准目录,不检索当前工作目录。 4、条件编译命令 有几个命令可对程序源代码的各部分有选择地进行编译,该过程称为条件编译。商业软件公司广泛应用条件编译来提供和维护某一程序的许多顾客版本。 #if、#else,#elif及#endif

能用版宏定义鼠标说明书

KINBAS宏定义鼠标设置说明书(通用版) 1.找到安装文件,双击此图示开始安装,按照提示一步步操作即可。下载地址在宝贝详情页,或找客服索取链接 2.鼠标支持LOL编程软件游戏宏,无需繁琐操作,一键设置(光速QA、酒桶E闪,盲僧R闪、盲僧4眼W瞬、盲僧2眼W瞬、猴子EAQ、皓月QR皇子二连、牛头二连,需要注意的是逆战和CF 这两个游戏屏蔽宏定义功能,在这两款游戏中可能暂时无法使用宏定义功能 一、基本设置:本自定义程序分三部分:基本设置;高级设置;呼吸灯设置 以设置5号键(看下图)宏功能为例,按下图大的蓝色数字123依次点击) 再点击大的蓝色数字4旁的“应用”按钮后,盲僧R闪功能设置成功 2.其它宏功能也是这样来按上面蓝色数字1 2 3步设置后,点第4步左边的应用两

个字,就设置成功了, 3.如果设置后按键功能需要恢复,点一下程序下面的“出厂设置”就可以恢复默认按 键功能了,或者退出我们的应该程序后,按键功能恢复默认 二.高级设置:录制自己需要的宏,这里的操作相对复杂一些(请根据步骤操作,用多几天,用熟悉了,设置也就不难了) 根据下图:运行软件,见下图数字数字操作指引:1点高级设置2在宏名称项中输入"测试宏"3点新增按钮,4.点录制,5,此时按下键盘你需要的操作(比如连续按下DDD),6此时第4步的录制变成了停止按钮,请点停止,7点保存按钮,录制完成 8点基本设置按此说明书的第1页基本设置使用方法里,选择自己刚才录制好的“测试宏”即可,请注意,(如果录制宏后没点停止,键盘此时在系统的操作是没反应的) 备注: 三.宏定义最多可设置12项,如超出,可删除平常少用快捷功能,再添加!另外,根据网速不同,可能有些宏需要调整,功能才得以实现。 四.呼吸灯设置:

C语言宏定义##连接符和#符的使用

C语言宏定义##连接符和#符的使用 C语言中如何使用宏C(和C++)中的宏(Macro)属于编译器预处理的范畴,属于编译期概念(而非运行期概念)。下面对常遇到的宏的使用问题做了简单总结。 关于#和## 在C语言的宏中,#的功能是将其后面的宏参数进行字符串化操作(Stringfication),简单说就是在对它所引用的宏变量通过替换后在其左右各加上一个双引号。比如下面代码中的宏: #define WARN_IF(EXP) do{ if (EXP) fprintf(stderr, "Warning: " #EXP "/n"); } while(0) 那么实际使用中会出现下面所示的替换过程: WARN_IF (divider == 0); 被替换为 do { if (divider == 0) fprintf(stderr, "Warning" "divider == 0" "/n"); } while(0); 这样每次divider(除数)为0的时候便会在标准错误流上输出一个提示信息。 而##被称为连接符(concatenator),用来将两个T oken连接为一个Token。注意这里连接的对象是T oken就行,而不一定是宏的变量。比如你要做一个菜单项命令名和函数指针组成的结构体的数组,并且希望在函数名和菜单项命令名之间有直观的、名字上的关系。那么下面的代码就非常实用: struct command { char * name; void (*function) (void); }; #define COMMAND(NAME) { NAME, NAME ## _command }

含参数的宏与函数的优缺点

1.函数调用时,先求出实参表达式的值,然后带入形参。而使用带参的宏只是进行简单的字符替换。 2.函数调用是在程序运行时处理的,分配临时的内存单元;而宏展开则是在编译时进行的,在展开时并不分配内存单元,不进行值的传递处理,也没有“返回值”的概念。 3.对函数中的实参和形参都要定义类型,二者的类型要求一致,如不一致,应进行类型转换;而宏不存在类型问题,宏名无类型,它的参数也无类型,只是一个符号代表,展开时带入指定的字符即可。宏定义时,字符串可以是任何类型的数据。 4.调用函数只可得到一个返回值,而用宏可以设法得到几个结果。 5.使用宏次数多时,宏展开后源程序长,因为每展开一次都使程序增长,而函数调用不使源程序变长。 6.宏替换不占运行时间,只占编译时间;而函数调用则占运行时间(分配单元、保留现场、值传递、返回)。 一般来说,用宏来代表简短的表达式比较合适。 内联函数和宏很类似,而区别在于,宏是由预处理器对宏进行替代,而内联函数是通过编译器控制来实现的。而且内联函数是真正的函数,只是在需要用到的时候,内联函数像宏一样的展开,所以取消了函数的参数压栈,减少了调用的开销。你可以象调用函数一样来调用内联函数,而不必担心会产生于处理宏的一些问题。 当然,内联函数也有一定的局限性。就是函数中的执行代码不能太多了,如果,内联函数的函数体过大,一般的编译器会放弃内联方式,而采用普通的方式调用函数。这样,内联函数就和普通函数执行效率一样了。内联函数是不能为虚函数的,但样子上写成了内联的,即隐含的内联方式。在某种情况下,虽然有些函数我们声明为了所谓“内联”方式,但有时系统也会把它当作普通的函数来处理,这里的虚函数也一样,虽然同样被声明为了所谓“内联”方式,但系统会把它当然非内联的方式来处理。

c中各类宏定义的用法

假设a.h内容如下: #ifndef AH #define AH typedef int INT; #endif b.h内容如下: #include "a.h" a.c内容如下: #include "a.h" #include "b.h" main() { INT a; } (1)如果a.h中不写#ifndef #define ... #endif的话 a.c展开结果会是下面这样: typedef int INT; typedef int INT; main() { INT a; } 编译结果会报标识符INT重复错误。 (2)如果a.h中加上#ifndef #define ... #endif的话 a.c展开结果会是下面这样: #ifndef AH #define AH

typedef int INT; #endif #ifndef AH #define AH typedef int INT; #endif main() { INT a; } 这样的话,因为程序中已经定义了一次AH,所以不会走到第二次声明INT的分支。所以不会出错。 #ifndef #define #endif的用法整理:shichenghua https://www.wendangku.net/doc/3313851084.html,/blog/?56085/action_viewspace_itemid_1145.htm l (前段时间要到这个,感觉shichenghua整理得不错,所以收藏到此处,若不同意,随时可以撤下 谢谢shichenghua) 文件中的#ifndef

头件的中的#ifndef,这是一个很关键的东西。比如你有两个C文件,这两个C文件都include了同一个头文件。而编译时,这两个C文件要一同编译成一个可运行文件,于是问题来了,大量的声明冲突。 还是把头文件的内容都放在#ifndef和#endif中吧。不管你的头文件会不会被多个文件引用,你都要加上这个。一般格式是这样的: #ifndef <标识> #define <标识> ...... ...... #endif <标识>在理论上来说可以是自由命名的,但每个头文件的这个“标识”都应该是唯一的。标识的命名规则一般是头文件名全大写,前后加下划线,并把文件名中的“.”也变成下划线,如:stdio.h #ifndef _STDIO_H_ #define _STDIO_H_ ...... #endif 2.在#ifndef中定义变量出现的问题(一般不定义在#ifndef中)。 #ifndef AAA #define AAA ... int i; ... #endif 里面有一个变量定义 在vc中链接时就出现了i重复定义的错误,而在c中成功编译。 结论:

Qt全局变量、函数和宏定义详解

头文件包含了 Qt 类库的一些全局定义,包括基本数据类型、函数和宏,一般的 Qt 类的头文件都会包含该文件,所以不用显式包含这个头文件也可以使用其中的定义。 全局变量定义 为了确保在各个平台上各数据类型都有统一确定的长度,Qt 为各种常见数据类型定义了类型符号,如 qint8 就是 signed char 的类型定义,即: 中定义的数据类型见表 1。 其中 qreal 缺省是 8 字节 double 类型浮点数,如果 Qt 使用-qreal float 选项进行配置,就是 4 字节 float 类型的浮点数。

qfloat16 是 Qt 5.9.0 中新增的一个类,用于表示 16 位的浮点数,要 使用 qfloat16,需要包含头文件 。 全局函数定义 头文件包含一些常用函数的定义,这些函数多以模板类型作为参数,返回相应的模板类型,模板类型可以用任何其他类型替换。若是以 double 或 float 类型数作为参数的,一般有两个参数版本的同名函数,如qFuzzyIsNull(double d) 和 qFuzzyIsNull(float f)。 表 2 是 中常用的全局函数定义,列出了函数的输入和输出参数(若存在 double 和 float 两种参数版本,只列出 double 类型参数的版本)。

还有一些基础的数学运算函数在 头文件中定义,比如三角运算函数、弧度与角度之间的转换函数等。 全局宏定义 中文件中定义了很多宏,以下一些是比较常用的: ?QT_VERSION:这个宏展开为数值形式 0xMMNNPP (MM = major, NN = minor, PP = patch) 表示 Qt 编译器版本,例如 Qt 编译器版本为 Qt 5.9.1,则 QT_VERSION 为 0x050901。这个宏常用于条件编译设置,根据 Qt 版本不同,编译不同的代码段。 ?QT_VERSION_CHECK:这个宏展开为 Qt 版本号的一个整数表示,例如: ?QT_VERSION_STR:这个宏展开为 Qt 版本号的字符串,如“5.9.0”。 ?Q_BYTE_ORDER、Q_BIG_ENDIAN 和 Q_LITTLE_ENDIAN:Q_BYTE_ORDER 表示系统内存中数据的字节序,Q_BIG_ENDIAN 表示大端字节序,Q_LITTLE_ ENDIAN 表示小端字节序。在需要判断系统字节序时会用到,例如:

c语言宏定义技巧

1,防止一个头文件被重复包含 #ifndef COMDEF_H #define COMDEF_H // 头文件内容 #endif 2,重新定义一些类型,防止由于各种平台和编译器的不同,而产生的类型字节数差异,方便移植。typedef unsigned char boolean; /* Boolean value type. */ typedef unsigned long int uint32; /* Unsigned 32 bIT value */ typedef unsigned short uint16; /* Unsigned 16 bit value */ typedef unsigned char uint8; /* Unsigned 8 bit value */ typedef signed long int int32; /* Signed 32 bit value */ typedef signed short int16; /* Signed 16 bit value */ typedef signed char int8; /* Signed 8 bit value */ //下面的不建议使用 typedef unsigned char byte; /* Unsigned 8 bit value type. */ typedef unsigned short word; /* Unsinged 16 bit value type. */ typedef unsigned long dword; /* Unsigned 32 bit value type. */ typedef unsigned char uint1; /* Unsigned 8 bit value type. */ typedef unsigned short uint2; /* Unsigned 16 bit value type. */ typedef unsigned long uint4; /* Unsigned 32 bit value type. */ typedef signed char int1; /* Signed 8 bit value type. */ typedef signed short int2; /* Signed 16 bit value type. */ typedef long int int4; /* Signed 32 bit value type. */ typedef signed long sint31; /* Signed 32 bit value */ typedef signed short sint15; /* Signed 16 bit value */ typedef signed char sint7; /* Signed 8 bit value */ 3,得到指定地址上的一个字节或字 #define MEM_B( x ) ( *( (byte *) (x) ) ) #define MEM_W( x ) ( *( (word *) (x) ) ) 4,求最大值和最小值 #define MAX( x, y ) ( ((x) > (y)) ? (x) : (y) ) #define MIN( x, y ) ( ((x) < (y)) ? (x) : (y) ) 5. 得到一个field在结构体(struct)中的偏移量 #define FPOS( type, field ) \ ( (dword) &(( type *) 0)-> field ) 6. 得到一个结构体中field所占用的字节数 #define FSIZ( type, field ) sizeof( ((type *) 0)->field )

宏定义

一、#define的基本用法 #define是C语言中提供的宏定义命令,其主要目的是为程序员在编程时提供一定的方便,并能在一定程度上提高程序的运行效率,但学生在学习时往往不能理解该命令的本质,总是在此处产生一些困惑,在编程时误用该命令,使得程序的运行与预期的目的不一致,或者在读别人写的程序时,把运行结果理解错误,这对 C语言的学习很不利。 1 #define命令剖析 1.1 #define的概念 #define命令是C语言中的一个宏定义命令,它用来将一个标识符定义为一个字符串,该标识符被称为宏名,被定义的字符串称为替换文本。 该命令有两种格式:一种是简单的宏定义,另一种是带参数的宏定义。 (1)简单的宏定义: #define<宏名><字符串> 例:#define PI 3.1415926 (2) 带参数的宏定义 #define<宏名>(<参数表>)<宏体> 例:#define A(x) x 一个标识符被宏定义后,该标识符便是一个宏名。这时,在程序中出现的是宏名,在该程序被编译前,先将宏名用被定义的字符串替换,这称为宏替换,替换后才进行编译,宏替换是简单的替换。 1.2 宏替换发生的时机 为了能够真正理解#define的作用,让我们来了解一下对C语言源程序的处理过程。当我们在一个集成的开发环境如Turbo C中将编写好的源程序进行编译时,实际经过了预处理、编译、汇编和连接几个过程。其中预处理器产生编译器的输出,它实现以下的功能: (1)文件包含 可以把源程序中的#include 扩展为文件正文,即把包含的.h文件找到并展开到#include 所在处。 (2)条件编译 预处理器根据#if和#ifdef等编译命令及其后的条件,将源程序中的某部分包含进来或排除在外,通常把排除在外的语句转换成空行。 (3)宏展开 预处理器将源程序文件中出现的对宏的引用展开成相应的宏定义,即本文所说的#define的功能,由预处理器来完成。

宏的意义和用法

在介绍学习VBA之前,应该花几分钟录制一个宏。 新术语:“宏”,指一系列EXCEL能够执行的VBA语句。 以下将要录制的宏非常简单,只是改变单元格颜色。请完成如下步骤: 1)打开新工作簿,确认其他工作簿已经关闭。 2)选择A1单元格。调出“常用”工具栏。 3)选择“工具”—“宏”—“录制新宏”。 4)输入“改变颜色”作为宏名替换默认宏名,单击确定,注意,此时状态栏中显示“录制”,特别是“停止录制”工具栏也显示出来。替换默认宏名主要是便于分别这些宏。★宏名最多可为255个字符,并且必须以字母开始。其中可用的字符包括:字母、数字和下划线。宏名中不允许出现空格。通常用下划线代表空格。 5)选择“格式”的“单元格”,选择“图案”选项中的红色,单击“确定”。 6)单击“停止录制”工具栏按钮,结束宏录制过程。 ※如果“停止录制”工具栏开始并未出现,请选择“工具”—“宏”—“停止录制”。 录制完一个宏后就可以执行它了。 1.4 执行宏 当执行一个宏时,EXCEL按照宏语句执行的情况就像VBA代码在对EXCEL进行“遥控”。但VBA的“遥控”不仅能使操作变得简便,还能使你获得一些使用EXCEL标准命令所无法实现的功能。而且,一旦熟悉了EXCEL的“遥控”,你都会奇怪自己在没有这些“遥控”的情况下,到底是怎么熬过来的。要执行刚才录制的宏,可以按以下步骤进行: 1)选择任何一个单元格,比如A3。 2)选择“工具”—“宏”—“宏”,显示“宏”对话框。 3)选择“改变颜色”,选择“执行”,则A3单元格的颜色变为红色。试着选择其它单元格和几个单元格组成的区域,然后再执行宏,以便加深印象。 1.5 查看录制的代码 到底是什么在控制EXCEL的运行呢?你可能有些疑惑.好,让我们看看VBA的语句吧. 1)选择“工具”—“宏”—“宏”,显示“宏”对话框。 2)单击列表中的“改变颜色”,选择“编辑”按钮。 此时,会打开VBA的编辑器窗口(VBE)。关于该编辑器,以后再详细说明,先将注意力集中到显示的代码上。代码如下:(日期和姓名会有不同) Sub 改变颜色() ' ' 改变颜色Macro ' xw 记录的宏2000-6-10 '

函数调用与宏定义巩固题

函数调用、宏定义 一.选择题(每题2分,共60分) 1.有以下函数调用语句: A fun(rec1,rec2+rec3,(rec4,rec5); 该函数调用语句中,含有的实参个数是。 A)3 B) 4 C)5 D)有语法错 2.有以下程序:D int fun(int a,int b) { return(a+b);} main() {int x=2,y=5,z=8,r; r=func(func(x,y),z); printf(“%d\n”,r); } 程序运行后的输出结果是。 A) 12 B)13 C) 14 D)15 3.有以下程序:C int abc(int u,int v) main() {int a=24,b=16,c; c=abc(a,b); printf(“%d\n”,c); } int abc(int u,int v) {int w; while(v) {w=u;u=v;v=w;} return u; } 程序运行后的输出结果是。 A) 6 B)7 C) 8 D) 9 4.以下程序的输出结果是。D #difine M(x,y,z) x*y+z main() {int a=1,b=2,c=3; printf(“%d\n”,M(a+b,b+c,c+a));} A) 19 B) 17 C) 15 D)12 5.有如下程序 #define N 2 #define M N+1 #define NUM 2*M+1 main() { int i; for(i=1;i<=NUM;i++) printf(“%d\n”,i);} 该循环中的for循环执行的次数是。B A) 5 B) 6 C) 7 D) 8 6.若已经定义的函数有返回值,则以下关于该函数调用的叙述中错误的是。D A) 函数调用可以作为独立的语句存在 B) 函数调用可以作为一个函数的实参 C)函数调用可以出现在表达式中

计算机c语言宏定义实例讲解

c语言宏定义使用之最全讲解 1宏定义 (1)宏定义的意义 宏定义简化了重复性的劳动,便于程序修改。我们常常会遇到需要修改一个特定的数字,然而这个数字在程序中很多地方都出现,譬如圆周率π,在之前的程序中我们取得精度是3.14,现在我们需要将精度改为3.1415926,这样在所有含有3.14的地方全部都去修改,太繁琐了,容易疏漏和出错。可以使用宏定义将字符串3.14给它定义一个标识符来代替,只需要修改标识符后的字符串,就达到全部修改的目的。这样既增加了程序的可读性,另外也避免了重复劳动,一般将宏定义放在头文件中,便于查找和提高了编程效率。但是同时要注意,标识符后的字符串在预处理中仅仅只是文本上的替换。相信读者这一点在之前的编译链接的章节中已经非常的熟悉了。 带参宏也可以减小函数调用的开销,能够简化复杂表达式。但是只是在文本上进行替换也会蒙蔽人们的双眼,下面内容详细地为大家解开迷雾。 (2)宏定义的规则和使用解析 (1)宏定义在预处理阶段由预处理器进行替换,这个替换是原封不动的替换。 (2)宏定义替换会递归进行,直到替换出来的值本身不再是一个宏为止。 (3)一个正确的宏定义本身分为三个部分:第一部分是#define,第二部分是宏名,剩下的所有 为第三部分。 (4)宏可以带参数,称为带参宏。带参宏的使用和带参函数非常像,但是使用上有一些差异。在 定义带参宏时,每一个参数在宏体中引用时都必须加括号,最后整体再加括号,括号缺一不可。 (3)无参数宏定义 无参宏的宏名后不带参数,定义的一般形式是: #define标识符宏体 标识符为符号常量,宏体为常数、表达式、格式串等 带参数宏定义举例:SEC_PER_YEAR,用宏定义表示一年中有多少秒 #define SEC_PER_YEAR(365*24*60*60UL) 365*24*60*60这个常整数的缺省类型为int。低位系统中(如16位系统),365*24*60*60这个数会整数溢出。所以将其转为无符号长整形,在其后加上UL(即unsigned long)。虽然在高位操作系统中,这个数字不会超出int的范围,可以不加UL;但是这样存在安全隐患。 (4)带参数宏定义 带参数宏定义举例:MAX宏,求2个数中较大的一个 #define MAX(a,b)(((a)>(b))?(a):(b)) 关键: 第一点:要想到使用三目运算符来完成;

C语言中的#的作用

c语言中的#号的作用 宏中"#"和"##"的用法 一、一般用法 我们使用#把宏参数变为一个字符串,用##把两个宏参数贴合在一起. 用法: #i nclude #i nclude using namespace std; #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 return0; }

二、当宏参数是另一个宏的时候 需要注意的是凡宏定义里有用'#'或'##'的地方宏参数是不会再展开. 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#i nclude 这行会被展开为: 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) #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型的最

相关文档