C语言宏操作大全

合集下载

C语言常用宏定义的用法介绍

C语言常用宏定义的用法介绍

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语言宏高级用法[总结]

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语言程序设计--宏

c语言程序设计--宏

2) #define MU(x,y) x*y a=MU(5,2)=5*2=10 b=6/MU(a+3,a)=6/a+3*a =6/10+3*10=30
#define PR(ar) printf(“ar=%d”,ar) printf(“ar=%d” Main() { int j,a[]={1,3,5,7,9,11,13,15},*p=a+5; for(j=3;j;j--) for(j=3;j;j--) switch(j) { case 1: case 2:PR(*P++);break’; 2:PR(*P++);break’ //printf (“ar=%d”,*p++); (“ar=%d” case 3:PR(*(--P)); 3:PR(*(--P)); // printf(“ar=%d”,*(--p)); printf(“ar=%d”,*(--p)); } } 结果:ar=9 结果:ar=9 ar=9 ar=11
如果不用宏。。。
(1) 程序的可读性(可理解性)变差。 程序员自己会忘记那些数字或字符串是什 么意思,用户则更加不知它们从何处来、 表示什么。 (2) 在程序的很多地方输入同样的数字 或字符串,难保不发生书写错误。 (3) 如果要修改数字或字符串,则会在 很多地方改动,既麻烦又容易出错。
宏使用的注意事项
三、终止宏定义
格式:#undef 格式:#undef 注意后面没有分号 例:#define 例:#define PI 3.14 main() { … #undef PI //在此之后,PI不再代表 //在此之后,PI不再代表 3.14 }
宏的定义
就是——字符替换 就是——字符替换 #defined A B

C语言中的宏定义

C语言中的宏定义
1. n = MAX(i, MAX(j,k));
下面是预处理后的这条语句:
1. n=((i)>(((j)>(k)?(j):(k)))?(i):(((j)>(k)?(j):(k))));
2) 、宏参数没有类型检查。当一个函数被调用时,编译器会检查每一个参数来确认它们是 否是正确的类型。如果不是,或者将参数转换成正确的类型,或者由编译器产生一个出错信 息。预处理器不会检查宏参数的类型,也不会进行类型转换。 3) 、无法用一个指针来指向一个宏。如在 17.7 节中将看到的,C 语言允许指针指向函数。 这一概念在特定的编程条件下非常有用。 宏会在预处理过程中被删除, 所以不存在类似的 “指 向宏的指针”。因此,宏不能用于处理这些情况。 4) 、宏可能会不止一次地计算它的参数。函数对它的参数只会计算一次,而宏可能会计算 两次甚至更多次。如果参数有副作用,多次计算参数的值可能会产生意外的结果。考虑下面 的例子,其中 MAX 的一个参数有副作用:
1. #define getchar() getc(stdin)
空的参数列表不是一定确实需要, 但可以使 getchar 更像一个函数。 (没错, 这就是<stdio.h> 中的 getchar,getchar 的确就是个宏,不是函数 ——虽然它的功能像个函数。) 使用带参数的宏替代实际的函数的优点: 1) 、 程序可能会稍微快些。一个函数调用在执行时通常会有些额外开销—— 存储上下文 信息、复制参数的值等。而一个宏的调用则没有这些运行开销。 2) 、 宏会更“通用”。与函数的参数不同,宏的参数没有类型。因此,只要预处理后的程序 依然是合法的,宏可以接受任何类型的参数。例如,我们可以使用 MAX 宏从两个数中选出 较大的一个,数的类型可以是 int,long int,float,double 等等。 但是带参数的宏也有一些缺点。

宏的基础语法

宏的基础语法

宏的基础语法由两部分组成:宏名和宏体。

在C语言中,宏定义使用“#define”命令,其基本语法形式为:复制代码
#define 宏名宏体
•宏名:是符合C语言变量规则的名字,一般使用大写表示。

•宏体:“替换文本”可以是任意常数、表达式、字符串等。

在预处理时,程序中所有出现的宏名都会被宏体替换。

这种替换是原地展开,没有调用开销,因此可以提高程序运行效率。

同时,使用宏定义可以方便程序修改,当在程序中需要多次使用某一个变量时,将其定义成一个宏可以避免多处同时修改。

请注意,宏定义和函数的最大差别是:宏定义是原地展开,因此没有调用开销;而函数是跳转执行再返回,因此函数有比较大的调用开销。

以上内容仅供参考,建议查阅C语言相关书籍或咨询技术专业人士以获取更准确的信息。

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程序的源代码中可包括各种编译指令,这些指令称为预处理命令。

虽然它们实际上不是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语言对宏命令的处理宏命令在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. 预处理阶段进行宏替换。

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

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];。

相关文档
最新文档