C语言宏操作大全
- 格式:pdf
- 大小:88.07 KB
- 文档页数:8
C语言常用宏定义的用法介绍C语言常用宏定义的用法介绍C语言中的宏定义是最常用的组成部分之一,他们在编程时有重要作用,正确应用可以减少很多代码工作量,但是使用过渡,则会造成可读性降低。
下面店铺给大家介绍C语言常用宏定义的用法介绍,欢迎阅读!C语言常用宏定义的用法介绍对于宏定义,需要注意以下说明:(1)宏名一般用大写;(2)使用宏可以提高程序的通用性和易读性,减少不一致性,减少输入错误和便于修改;(3)预处理是在编译之前的处理,预处理不做语法检查;(4)宏定义末尾没有分号;//不加;(5)宏定义自然作用域为从定义开始一直到本文件结尾;(6)可以用#undef命令提前终止宏定义的自然作用域;(7)宏定义可以嵌套;(8)字符串“”中永远不包含宏;(9)宏定义不会分配内存,变量定义分配内存;(10)宏定义不存在类型问题,它的参数也是无类型的,它仅仅是替换;(11)宏定义可以带参数,但需要注意的'是每个参数是一个整体,在定义体中要注意括起来。
下面列举了一些非常常用的宏定义用法:常数定义#define PI 3.1415926防止重复包含#ifndef __MY_HEAD_H__#define __MY_HEAD_H__...//这里的内容可以保证不被重复包含#endif求最大最小值#define GET_MAX(x, y) (((x) >= (y)) ? (x) : (y))#define GET_MIN(x, y) (((x) <= (y)) ? (x) : (y))得到结构体成员的偏移#define FPOS(type, field) ((unsigned long)&((type *)0)->field) 拼接字节为字#define MAKEWORD(h, l) (((h)<<8) | (l))#define MAKEDWORD(h, l) (((h)<<16) | (l))获得高、地位字节或者字#define WORD_LO(w) ((unsigned char)((w) & 0xFF))#define WORD_HI(w) ((unsigned char)((w) >> 8))#define DWORD_LO(dw) ((unsigned short)((dw) & 0xFFFF)) #define DWORD_HI(dw) ((unsigned short)((dw) >> 16))将一个字母转换为大写#define UPCASE(c) (((c) >= 'a' && (c) <= 'z') ? ((c) – 0x20) : (c))判断字符是不是10进值的数字#define DECCHK(c) ((c) >= '0' && (c) <= '9')判断字符是不是16进值的数字#define HEXCHK(c) (((c) >= '0' && (c) <= '9') || ((c) >= 'A' && (c) <= 'F') || ((c) >= 'a' && (c) <= 'f'))返回数组元素的个数#define ARR_SIZE(a) (sizeof((a))/sizeof(((a)[0])))【C语言常用宏定义的用法介绍】。
C语⾔宏⾼级⽤法[总结]1、前⾔ 今天看代码时候,遇到⼀些宏,之前没有见过,感觉挺新鲜。
如是上⽹google⼀下,顺便总结⼀下,⽅便以后学习和运⽤。
C语⾔程序中⼴泛的使⽤宏定义,采⽤关键字define进⾏定义,宏只是⼀种简单的字符串替换,根据是否带参数分为⽆参和带参。
宏的简单应⽤很容易掌握,今天主要总结⼀下宏的特殊符号及惯⽤法。
(1)宏中包含特殊符号:#、##.(2)宏定义⽤do{ }while(0)2、特殊符号#、##(1)# When you put a # before an argument in a preprocessor macro, the preprocessor turns that argument into a character array. 在⼀个宏中的参数前⾯使⽤⼀个#,预处理器会把这个参数转换为⼀个字符数组 简化理解:#是“字符串化”的意思,出现在宏定义中的#是把跟在后⾯的参数转换成⼀个字符串#define ERROR_LOG(module) fprintf(stderr,"error: "#module"\n")ERROR_LOG("add"); 转换为 fprintf(stderr,"error: "add"\n");ERROR_LOG(devied =0); 转换为 fprintf(stderr,"error: devied=0\n");(2)## “##”是⼀种分隔连接⽅式,它的作⽤是先分隔,然后进⾏强制连接。
在普通的宏定义中,预处理器⼀般把空格解释成分段标志,对于每⼀段和前⾯⽐较,相同的就被替换。
但是这样做的结果是,被替换段之间存在⼀些空格。
如果我们不希望出现这些空格,就可以通过添加⼀些##来替代空格。
1#define TYPE1(type,name) type name_##type##_type2#define TYPE2(type,name) type name##_##type##_typeTYPE1(int, c); 转换为:int name_int_type ; (因为##号将后⾯分为 name_ 、type 、 _type三组,替换后强制连接)TYPE2(int, d);转换为: int d_int_type ; (因为##号将后⾯分为 name、_、type 、_type四组,替换后强制连接)3、宏定义中do{ }while(0) 第⼀眼看到这样的宏时,觉得⾮常奇怪,为什么要⽤do……while(0)把宏定义的多条语句括起来?⾮常想知道这样定义宏的好处是什么,于是google、百度⼀下了。
宏的基础语法由两部分组成:宏名和宏体。
在C语言中,宏定义使用“#define”命令,其基本语法形式为:复制代码
#define 宏名宏体
•宏名:是符合C语言变量规则的名字,一般使用大写表示。
•宏体:“替换文本”可以是任意常数、表达式、字符串等。
在预处理时,程序中所有出现的宏名都会被宏体替换。
这种替换是原地展开,没有调用开销,因此可以提高程序运行效率。
同时,使用宏定义可以方便程序修改,当在程序中需要多次使用某一个变量时,将其定义成一个宏可以避免多处同时修改。
请注意,宏定义和函数的最大差别是:宏定义是原地展开,因此没有调用开销;而函数是跳转执行再返回,因此函数有比较大的调用开销。
以上内容仅供参考,建议查阅C语言相关书籍或咨询技术专业人士以获取更准确的信息。
c语言条件宏判断摘要:1.条件宏概述2.条件宏的语法3.条件宏的运算符4.条件宏的注意事项5.条件宏的实际应用正文:C 语言中的条件宏是一种根据不同的条件执行不同代码块的宏。
它们可以根据表达式的值来选择执行哪个分支的代码。
条件宏的语法如下:```c#if 表达式代码块1#elif 表达式代码块2#else代码块3#endif```其中,`#if`、`#elif`、`#else`和`#endif`是预处理指令,用于指定条件宏的分支。
表达式可以是任意的C 语言表达式,用于判断条件。
条件宏的运算符主要有以下几种:1.逻辑运算符:`&&`(逻辑与)、`||`(逻辑或)、`!`(逻辑非)。
2.关系运算符:`<`(小于)、`>`(大于)、`<=`(小于等于)、`>=`(大于等于)、`==`(等于)、`!=`(不等于)。
3.类型转换运算符:`int`、`float`、`double`等。
在编写条件宏时,需要注意以下几点:1.每个`#if`、`#elif`、`#else`和`#endif`指令必须成对出现,且`#endif`必须放在文件的末尾。
2.条件宏内的代码块需要用花括号括起来,例如`{}`。
3.条件宏内的代码块可以包含多条语句。
条件宏在实际编程中有很多应用,例如根据不同的编译器或平台选择不同的代码实现、根据用户输入的选项执行相应的功能等。
下面是一个简单的例子:```c#include <stdio.h>#define MAX(a, b) ((a) > (b) ? (a) : (b))int main() {int a = 5, b = 10;int max = MAX(a, b);printf("较大的数是:%d", max);return 0;}```在这个例子中,我们定义了一个名为`MAX`的条件宏,用于计算两个数的较大值。
C语⾔预处理命令总结⼤全:宏定义C程序的源代码中可包括各种编译指令,这些指令称为预处理命令。
虽然它们实际上不是C语⾔的⼀部分,但却扩展了C程序设计的环境。
本节将介绍如何应⽤预处理程序和注释简化程序开发过程,并提⾼程序的可读性。
ANSI标准定义的C语⾔预处理程序包括下列命令:#define,#error,#include,#if,#else,#elif,#endif,#ifdef,#ifndef,#undef,#line,#pragma等。
⾮常明显,所有预处理命令均以符号#开头,下⾯分别加以介绍。
⼀ #define命令#define定义了⼀个标识符及⼀个串。
在源程序中每次遇到该标识符时,均以定义的串代换它。
ANSI标准将标识符定义为宏名,将替换过程称为宏替换。
命令的⼀般形式为:#define ID string注意:1该语句没有分号。
在标识符和串之间可以有任意个空格,串⼀旦开始,仅由⼀新⾏结束。
2宏名定义后,即可成为其它宏名定义中的⼀部分。
3 宏替换仅仅是以⽂本串代替宏标识符,前提是宏标识符必须独⽴的识别出来,否则不进⾏替换。
例如:#define XYZ this is a tes使⽤宏printf("XYZ");//该段不打印"this is a test"⽽打印"XYZ"。
因为预编译器识别出的是"XYZ"4如果串长于⼀⾏,可以在该⾏末尾⽤⼀反斜杠' \'续⾏。
#defineLONG_STRING"this is a very long\string that is used as an example"5 C语⾔程序普遍使⽤⼤写字母定义标识符。
6 ⽤宏代换代替实在的函数的⼀⼤好处是宏替换增加了代码的速度,因为不存在函数调⽤的开销。
但增加速度也有代价:由于重复编码⽽增加了程序长度。
c语言对宏命令的处理-回复C语言对宏命令的处理宏命令在C语言中扮演着非常重要的角色。
通过使用宏命令,我们可以在程序中定义一些特殊的符号,以方便编码和代码的重复使用。
宏命令可以简化程序的编写过程,提高代码的可读性和可维护性。
本文将一步一步回答关于C语言对宏命令的处理的问题。
一、什么是宏命令?宏命令是一种预处理指令,用于替换代码中的符号。
宏命令使用define关键字进行定义,并可以接受参数。
在预处理阶段,编译器将宏命令替换为与之对应的代码片段。
宏命令的语法格式通常为:define 宏名参数列表代码片段其中,宏名是一个标识符,用于表示我们要定义的宏命令的名称;参数列表用于表示宏命令接受的参数,可以为空;代码片段为替换宏命令的具体代码。
二、宏命令的作用是什么?宏命令的作用主要有两个方面:代码替换和代码复用。
1. 代码替换:宏命令可以将一段代码片段替换成一个符号。
通过使用宏命令,我们可以将一些频繁重复出现的代码片段替换成一个宏名,以提高代码的可读性和可维护性。
例如,我们可以使用宏命令将一个常用的数学计算公式替换成一个符号,以简化代码编写过程。
2. 代码复用:宏命令可以实现代码的复用。
通过定义宏命令并将其包含在不同的代码片段中,可以实现代码的复用。
这样,在需要使用该代码片段的地方,只需要调用对应的宏命令即可,无需重复编写相同的代码。
三、宏命令的使用方法有哪些?使用宏命令的一般步骤如下:1. 使用define关键字进行宏命令的定义。
定义时需要指定宏名、参数列表和代码片段。
例如,我们要定义一个用于计算两个数之和的宏命令ADD:define ADD(a, b) ((a) + (b))其中,宏名为ADD,参数列表为(a, b),代码片段为((a) + (b))。
2. 在代码中使用宏命令。
在需要用到宏命令的地方,直接使用宏名并传入参数。
例如,我们要计算两个整数的和:int sum = ADD(3, 4);3. 预处理阶段进行宏替换。
c语言宏定义用法规则C语言宏定义是一种C语言中最常使用的技术,它可以将经常使用的长句子等缩短,可以将复杂的语句也变得更加简单。
使用宏定义,可以提高程序的可读性,使程序更加便于维护和修改,并且可以更加高效地使用程序。
一、宏定义的语法形式C语言的宏定义的语法有以下几种格式:1. #define:#define宏定义用于定义字符串宏或符号宏,本质上它就是把特定的字符串或符号,映射到一个相应的宏名称。
例如:#define PI 3.14159293表示宏定义一个PI,其值为3.141592932. #undef:#undef用于取消宏定义,例如:#undef PI表示取消之前定义流程中的PI宏定义;3. #ifdef:#ifdef可以根据宏定义的存在与否,在程序编译时有选择性的执行一段代码,例如:#ifdef PIprintf("PI is define\n");#endif上述代码表示:如果PI的宏定义存在的话,则编译执行printf("PI is define\n"),否则不执行。
C语言宏定义可以使用参数,这些参数可以是函数、符号、字符串或者表达式,它们都可以在宏定义中扮演角色,使用参数可以提高宏的可扩展性,从而提高程序的复用性,简化程序的结构。
1. 宏定义参数的表示参数的格式使用形式参数名称来表示,一般使用字母a~z表示参数,形式参数可以使用多次,但参数名必须是唯一的。
例如:#define MIN(x, y) ((x) < (y))? (x): (y)这是一个使用参数的宏定义示例,其中参数x,y是表示形式参数的名称,宏定义的意思是返回x和y的较小值。
使用宏定义参数需要在宏定义时明确参数的含义,每个参数都必须有明确的含义,有利于后续的维护和修改。
例如:三、C语言宏定义书写规范1. #define是注释符号,使用时要在一行的开头,以#开头,表示此行的内容是宏定义,且宏定义的关键词必须全大写。
c语言宏高级用法宏是C语言中一种强大的工具,可以在编译阶段对代码进行替换和扩展。
除了常见的宏定义,C语言还有一些高级用法可以进一步提升宏在程序中的灵活性和效率。
首先,C语言中的宏可以接受变长参数,使得宏的调用更加灵活。
通过在宏定义中使用省略号(...)表示可变参数,我们可以在宏内对可变参数进行处理。
例如,可以定义一个可变参数的宏来实现类似printf函数的功能:```#define PRINTF(format, ...) printf(format, __VA_ARGS__)```这样,我们就可以使用宏来输出格式化的信息:```PRINTF("Hello, %s! Today is %d-%d-%d.", name, year, month, day);```其次,宏还可以使用条件编译来实现在不同情况下的不同行为。
通过在宏定义中使用#if、#elif、#else和#endif预处理指令,可以在编译时根据条件选择性地定义宏。
这在一些需要根据不同平台或编译选项进行不同处理的场景中非常有用。
例如:```#if defined(WIN32)#define PLATFORM_NAME "Windows"#elif defined(LINUX)#define PLATFORM_NAME "Linux"#else#define PLATFORM_NAME "Unknown"#endif```最后,C语言的宏还可以帮助我们编写通用且高效的代码。
通过宏的替换规则,我们可以在编译阶段对代码进行优化。
例如,可以使用宏来定义简单的位操作:```#define SET_BIT(var, bit) ((var) |= (1 << (bit)))#define CLEAR_BIT(var, bit) ((var) &= ~(1 << (bit)))```这样,我们就可以使用宏以更简洁的方式进行位操作:```SET_BIT(flags, 3);CLEAR_BIT(flags, 7);```总之,C语言中宏的高级用法可以提供更多灵活性和效率。
C语言宏操作(来源于网络)写好C语言,漂亮的宏定义很重要,使用宏定义可以防止出错,提高可移植性,可读性,方便性等等。
下面列举一些成熟软件中常用得宏定义。
1,防止一个头文件被重复包含#ifndef COMDEF_H#define COMDEF_H//头文件内容#endif2,重新定义一些类型,防止由于各种平台和编译器的不同,而产生的类型字节数差异,方便移植。
typedef unsigned char boolean;/*Boolean value type. */typedef unsigned long int uint32;/*Unsigned32bit value*/typedef unsigned short uint16;/*Unsigned16bit value*/typedef unsigned char uint8;/*Unsigned8bit value*/typedef signed long int int32;/*Signed32bit value */typedef signed short int16;/*Signed16bit value*/typedef signed char int8;/*Signed8bit value*///下面的不建议使用typedef unsigned char byte;/*Unsigned8bit value type.*/typedef unsigned short word;/*Unsinged16bit value type.*/typedef unsigned long dword;/*Unsigned32bit value type.*/typedef unsigned char uint1;/*Unsigned8bit value type.*/typedef unsigned short uint2;/*Unsigned16bit value type.*/typedef unsigned long uint4;/*Unsigned32bit value type.*/typedef signed char int1;/*Signed8bit value type.*/typedef signed short int2;/*Signed16bit value type.*/typedef long int int4;/*Signed32 bit value type.*/typedef signed long sint31;/*Signed32bit value*/typedef signed short sint15;/*Signed16bit value*/typedef signed char sint7;/*Signed8bit 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)\/*lint-e545*/((dword)&((type*)0)->field)/*lint+e545*/ 6,得到一个结构体中field所占用的字节数#define FSIZ(type,field)sizeof(((type*)0)->field)7,按照LSB格式把两个字节转化为一个Word#define FLIPW(ray)((((word)(ray)[0])*256)+(ray)[1])8,按照LSB格式把一个Word转化为两个字节#define FLOPW(ray,val)\(ray)[0]=((val)/256);\(ray)[1]=((val)&0xFF)9,得到一个变量的地址(word宽度)#define B_PTR(var)((byte*)(void*)&(var))#define W_PTR(var)((word*)(void*)&(var))10,得到一个字的高位和低位字节#define WORD_LO(xxx)((byte)((word)(xxx)&255))#define WORD_HI(xxx)((byte)((word)(xxx)>>8))11,返回一个比X大的最接近的8的倍数#define RND8(x)((((x)+7)/8)*8)12,将一个字母转换为大写#define UPCASE(c)(((c)>='a'&&(c)<='z')?((c)-0x20):(c)) 13,判断字符是不是10进值的数字#define DECCHK(c)((c)>='0'&&(c)<='9')14,判断字符是不是16进值的数字#define HEXCHK(c)(((c)>='0'&&(c)<='9')||\((c)>='A'&&(c)<='F') ||\((c)>='a'&&(c)<='f'))15,防止溢出的一个方法#define INC_SAT(val)(val=((val)+1>(val))?(val)+1:(val))16,返回数组元素的个数#define ARR_SIZE(a)(sizeof((a))/sizeof((a[0])))17,返回一个无符号数n尾的值MOD_BY_POWER_OF_TWO(X,n)=X%(2^n)#define MOD_BY_POWER_OF_TWO(val,mod_by)\((dword)(val)&(dword)((mod_by)-1))18,对于IO空间映射在存储空间的结构,输入输出处理#define inp(port)(*((volatile byte*)(port)))#define inpw(port)(*((volatile word*)(port)))#define inpdw(port)(*((volatile dword*)(port)))#define outp(port,val)(*((volatile byte*)(port))=((byte) (val)))#define outpw(port,val)(*((volatile word*)(port))=((word)(val)))#define outpdw(port,val)(*((volatile dword*)(port))=((dword) (val)))[2005-9-9添加]19,使用一些宏跟踪调试A N S I标准说明了五个预定义的宏名。
它们是:_L I N E__F I L E__D A T E__T I M E__S T D C_如果编译不是标准的,则可能仅支持以上宏名中的几个,或根本不支持。
记住编译程序也许还提供其它预定义的宏名。
_L I N E_及_F I L E_宏指令在有关#l i n e的部分中已讨论,这里讨论其余的宏名。
_D AT E_宏指令含有形式为月/日/年的串,表示源文件被翻译到代码时的日期。
源代码翻译到目标代码的时间作为串包含在_T I M E_中。
串形式为时:分:秒。
如果实现是标准的,则宏_S T D C_含有十进制常量1。
如果它含有任何其它数,则实现是非标准的。
可以定义宏,例如:当定义了_DEBUG,输出数据信息和所在文件所在行#ifdef_DEBUG#define DEBUGMSG(msg,date)printf(msg);printf(“%d%d%d”,date,_LINE_,_FILE_)#else#define DEBUGMSG(msg,date)#endif20,宏定义防止使用是错误用小括号包含。
例如:#define ADD(a,b)(a+b)用do{}while(0)语句包含多语句防止错误例如:#difne DO(a,b)a+b;\a++;应用时:if(….)DO(a,b);//产生错误else解决方法:#difne DO(a,b)do{a+b;\a++;}while(0)宏中"#"和"##"的用法一、一般用法我们使用#把宏参数变为一个字符串,用##把两个宏参数贴合在一起.用法:#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("%d\n",CONS(2,3));//2e3输出:2000return0;}二、当宏参数是另一个宏的时候需要注意的是凡宏定义里有用'#'或'##'的地方宏参数是不会再展开.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<climits>这行会被展开为: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 型的最大值,为一个变量#include<climits>输出为:int max:0x7fffffffSTR(INT_MAX)-->_STR(0x7fffffff)然后再转换成字符串;printf("%d\n",CONS(A,A));输出为:200CONS(A,A)-->_CONS((2),(2))-->int((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(0x7fffffff)];-->char buf[sizeof"0x7fffffff"];这里相当于:char buf[11];。