c中各类宏定义的用法
简述C语言宏定义的使用
简述C语言宏定义的使用1 概述在工程规模较小,不是很复杂,与硬件结合紧密,要求移植性的时候,可采用宏定义简化编程,增强程序可读性。
当宏作为常量使用时,C程序员习惯在名字中只使用大写字母。
但是并没有如何将用于其他目的的宏大写的统一做法。
由于宏(特别是带参数的宏)可能是程序中错误的来源,所以一些程序员更喜欢使用大写字母来引起注意。
1.简单宏定义无参宏的宏名后不带参数,其定义的一般形式为:#define 标识符字符串// 不带参数的宏定义#define MAX 10注意:不要在宏定义中放置任何额外的符号,比如"="或者尾部加";"使用#define来为常量命名一些优点:•程序会更易读。
一个认真选择的名字可以帮助读者理解常量的意义;•程序会更易于修改。
我们仅需要改变一个宏定义,就可以改变整个程序中出现的所有该常量的值;•可以帮助避免前后不一致或键盘输入错误;•控制条件编译;•可以对C语法做小的修改;1.带参数的宏带参数的仍要遵循上述规则,区别只是宏名后面紧跟的圆括号中放置了参数,就像真正的函数那样。
#define <宏名>(<参数列表>) <宏体>注意参数列表中的参数必须是有效的c标识符,同时以,分隔算符优先级问题:#define COUNT(M) M*Mint x=5;print(COUNT(x+1));print(COUNT(++X));//结果输出:11 和42 而不是函数的输出36注意:•预编译器只是进行简单的文本替换,COUNT(x+1)被替换成COUNT(x+1x+1),5+15+1=11,而不是36•CUNT(++x)被替换成++x*++x即为67=42,而不是想要的66=36,连续前置自加加两次解决办法:•用括号将整个替换文本及每个参数用括号括起来print(COUNT((x+1));•即便是加上括号也不能解决第二种情况,所以解决办法是尽量不使用++,-等符号;分号吞噬问题:#define foo(x) bar(x); baz(x)假设这样调用:if (!feral)foo(wolf);将被宏扩展为:if (!feral)bar(wolf);baz(wolf);==baz(wolf);==,不在判断条件中,显而易见,这是错误。
c语言宏的用法
c语言宏的用法C语言程序中广泛的使用宏定义,采用关键字define进行定义,宏只是一种简单的字符串替换,根据是否带参数分为无参和带参。
宏的简单应用很容易掌握,下面小编就跟大家分享下c语言宏的用法。
c语言宏的用法如下:1.宏的基本构成(1)宏中包含特殊符号:#、##.(2)宏定义用do{ }while(0)2、特殊符号#、##(1)#Whenyouputa#beforeanargumentinapreprocessor macro,thepreprocessorturnsthatargumentintoacharacterarray.在一个宏中的参数前面使用一个#,预处理器会把这个参数转换为一个字符数组简化理解:#是“字符串化”的意思,出现在宏定义中的#是把跟在后面的参数转换成一个字符串#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的全部使用方法介绍
C语言中define的全部使用方法介绍C语言中define的全部使用方法介绍设备驱动代码中有很多这样或者那样的宏定义,各种define,那么,你了解define的全部使用方法吗?下面店铺给大家介绍C语言中define的全部使用方法,欢迎阅读!C语言中define的全部使用方法介绍1. 最最最简单的 define 定义不赘述了,说一下其他的吧,如#define MAX 10,编译器在处理这个代码之前会对MAX进行处理,替换为10,或许有些人认为这样的定义看起来和const常量很相似,但是他们还是有区别的,#define 的定义其实就是简单的文本的`替换,并不是作为一个量来使用2. 用 #define 来对函数进行“定义”很多就会问了,什么?居然还能用#define来定义函数,坑爹么?其实咋说呢,就是类似的一个函数定义罢了,和真正的函数定义当然还是有区别的了,下面进行举例说明:还是用上面的MAX的例子:#define MAX(a,b) ((a) > (b) ? (a) : (b))这个定义就返回两个数中较大的那个,不知道你们看到了没看到,这个”函数“没有类型检查,像不像函数模板?像?不像?其实是有点像的,可以作为一个普通的模板来使用罢了,他肯定没函数模板那么安全,WHY?看下面的例子:#define MINUS(a,b) a –b,眨眼一看,这个肯定是减法操作的define,有木有?对,没错,就是这个意思,这个定义在一般的使用中没问题,但是在特定的情况下使用会出现问题,如果我们要这样去使用的话,展开之后会是什么样子呢?如:2 * MINUS(a,b) / 4,就像我前面所说的那样,宏其实就是一个简单的文本替换,所以展开时候就变为 2 * a – b / 4,和我们想要的结果是不是不一样?是不是错了?有木有?那要如何解决这个问题呢,很简单,给原定义加一个括号就OK 了,也就是#define MINUS(a,b) (a – b)再说一个经常出现的一个错误,看下面的例子:#define pin int *pin a,b;本意其实都想让a和b成为int型指针,但是实际上却变成了int *a,b;a是int型指针,b是int型变量,咋处理捏?这个时候typedef 就出来了,它说我可以满足define满足不了的要求,所以改成typedef pin (int *)就OK了。
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语言宏定义】来,看看这20个常用的宏定义!
【C语⾔宏定义】来,看看这20个常⽤的宏定义!写好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 )/*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)))——————————————19、使⽤⼀些宏跟踪调试A N S I标准说明了五个预定义的宏名。
C语言宏定义使用技巧[1]
C语言宏定义使用技巧写好C语言,漂亮的宏定义很重要,使用宏定义可以防止出错,提高可移植性,可读性,方便性等等。
下面列举一些成熟软件中常用得宏定义。
1, 防止一个头文件被重复包含#ifndef COMDEF_H#define COMDEF_H//头文件内容#endif2,重新定义一些类型,防止由于各种平台和编译器的不同,而产生的类型字节数差异,方便移植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 */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(***) ((byte) ((word)(***) & 255))#define WORD_HI(***) ((byte) ((word)(***) >> 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))) 19,使用一些宏跟踪调试A N S I标准说明了五个预定义的宏名。
c语言宏操作大全
C语言宏操作(来源于网络)写好C语言,漂亮的宏定义很重要,使用宏定义可以防止出错,提高可移植性,可读性,方便性等等。
下面列举一些成熟软件中常用得宏定义。
1,防止一个头文件被重复包含#ifndef COMDEF_H#define COMDEF_H//头文件内容#endif2,重新定义一些类型,防止由于各种平台和编译器的不同,而产生的类型字节数差异,方便移植。
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 ) \/*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标准说明了五个预定义的宏名。
c语言中宏定义
c语言中宏定义宏定义是C语言中一种非常重要的特性,通过宏定义可以简化代码,提高代码的可维护性和可读性。
在C语言中,宏定义是通过#define指令来实现的,可以定义常量、函数宏以及条件编译等。
首先,我们来看一下如何定义常量宏。
在C语言中,我们可以使用#define指令定义常量,例如:#define PI 3.14159。
这样,每次在代码中使用PI时,编译器会将其替换为3.14159。
常量宏的定义格式为#define 宏名值。
除了定义常量,宏定义还可以用来定义函数宏。
函数宏是一种宏定义,可以像函数一样接受参数,并返回一个值。
例如,我们可以定义一个计算平方的函数宏:#define SQUARE(x) ((x) * (x))。
在使用时,可以像函数一样传入参数,编译器会将其替换为对应的表达式。
另外,宏定义还可以用于条件编译,即根据条件编译指令来决定编译哪些代码。
例如,我们可以使用宏定义来控制代码的编译,如下所示:#ifdef DEBUGprintf("Debug mode\n");#endif在这段代码中,如果定义了DEBUG宏,则会打印“Debug mode”,否则不会打印。
条件编译可以根据宏定义的真假来选择性地编译代码,提高代码的灵活性和可移植性。
此外,宏定义还可以用于定义一些特定的编译器指令,如调试信息、优化等。
通过宏定义,我们可以根据不同的编译选项定义不同的宏,以达到不同的编译效果。
总的来说,宏定义是C语言中一种非常有用的特性,可以简化代码、提高代码的可维护性和可读性,同时还可以用于条件编译、函数宏等方面。
合理地使用宏定义,可以使代码更加灵活、高效。
希望以上内容对您有所帮助。
如果有其他问题,欢迎继续提问。
感谢阅读!。
define宏定义的用法
define宏定义的用法宏定义是C语言中的一个重要特性,它可以让程序员在编写代码时定义一些常量、函数或代码块,从而简化代码的编写和维护。
本文将详细介绍define宏定义的用法,帮助读者更好地理解和使用宏定义。
一、宏定义的基本语法宏定义的基本语法如下:#define 宏名宏值其中,宏名可以是任意的合法标识符,宏值可以是任意的C语言表达式或语句。
宏定义通常放在程序的开头,以便在整个程序中都可以使用。
例如,我们可以定义一个常量PI:#define PI 3.1415926这样,在程序中使用PI时就不需要手动输入3.1415926,可以直接使用宏名PI代替。
二、宏定义的作用宏定义的作用有以下几个方面:1、定义常量宏定义可以定义常量,方便程序员在代码中使用。
例如,我们可以定义一个常量MAX_SIZE表示数组的最大长度:#define MAX_SIZE 100这样,在程序中使用MAX_SIZE时,就不需要手动输入100,可以直接使用宏名MAX_SIZE代替。
2、定义函数宏定义可以定义函数,方便程序员在代码中使用。
例如,我们可以定义一个函数求两个数中的最大值:#define MAX(a,b) ((a)>(b)?(a):(b))这样,在程序中使用MAX(a,b)时,就可以得到a和b中的最大值。
注意,宏定义中的参数a和b必须用括号括起来,以避免出现优先级问题。
3、定义代码块宏定义可以定义代码块,方便程序员在代码中使用。
例如,我们可以定义一个代码块用于输出调试信息:#define DEBUG(fmt,args...) printf(fmt,##args) 这样,在程序中使用DEBUG(fmt,args...)时,就可以输出调试信息。
注意,宏定义中的fmt和args必须用省略号表示可变参数,以支持不同个数的参数。
三、宏定义的注意事项在使用宏定义时,需要注意以下几个问题:1、宏定义的作用域宏定义的作用域通常是整个程序,除非在某个代码块中重新定义了同名的宏。
c语言宏定义用法
在C语言中,宏定义是一种预处理指令,用来将一个标识符或一段代码片段替换为指定的文本。
宏定义的形式为#define,具体用法如下:.定义常量:可以使用宏定义来定义常量,例如:
#define PI 3.14159
在后续的代码中,可以使用PI来代替3.14159。
.定义函数形式的宏:可以使用宏定义来定义一段代码片段,例如:
#define SQUARE(x) ((x) * (x))
在后续的代码中,可以使用SQUARE(x)来代替(x) * (x),其中x是一个参数。
.定义带参数的宏:宏定义也可以带有参数,例如:
#define MAX(a, b) ((a) > (b) ? (a) : (b))在后续的代码中,可以使用MAX(a, b)来代替((a) > (b) ? (a) :
(b)),其中a和b是两个参数。
需要注意的是,宏定义只是简单的文本替换,没有类型检查和作用域限制。
因此,在使用宏定义时需要小心避免出现意外的副作用。
此外,为了提高可读性和避免错误,通常会将宏定义的替换文本用括号括起来,避免优先级问题。
C语言常用宏定义的用法介绍
C语言常用宏定义的用法介绍C语言中的宏定义是最常用的组成部分之一,他们在编程时有重要作用,正确应用可以减少很多代码工作量,但是使用过渡,则会造成可读*降低。
下面小编给大家介绍C语言常用宏定义的用法介绍,欢迎阅读!对于宏定义,需要注意以下说明:(1)宏名一般用大写;(2)使用宏可以提高程序的通用*和易读*,减少不一致*,减少输入错误和便于修改;(3)预处理是在编译之前的处理,预处理不做语法检查;(4)宏定义末尾没有分号;//不加;(5)宏定义自然作用域为从定义开始一直到本文件结尾;(6)可以用#undef命令提前终止宏定义的自然作用域;(7)宏定义可以嵌套;(8)字符串“”中永远不包含宏;(9)宏定义不会分配内存,变量定义分配内存;(10)宏定义不存在类型问题,它的参数也是无类型的,它仅仅是替换;(11)宏定义可以带参数,但需要注意的是每个参数是一个整体,在定义体中要注意括起来。
下面列举了一些非常常用的宏定义用法:常数定义#definePI3.1415926防止重复包含#ifndef__MY_HEAD_H__#define__MY_HEAD_H__...//这里的内容可以保*不被重复包含#endif求最大最小值#defineGET_MAX(x,y)(((x)>=(y))?(x):(y))#defineGET_MIN(x,y)(((x)<=(y))?(x):(y))得到结构体成员的偏移#defineFPOS(type,field)((unsignedlong)&((type*)0)->field) 拼接字节为字#defineMAKEWORD(h,l)(((h)<<8)|(l))#defineMAKEDWORD(h,l)(((h)<<16)|(l))获得高、地位字节或者字#defineWORD_LO(w)((unsignedchar)((w)&0xFF))#defineWORD_HI(w)((unsignedchar)((w)>>8))#defineDWORD_LO(dw)((unsignedshort)((dw)&0xFFFF))#defineDWORD_HI(dw)((unsignedshort)((dw)>>16))将一个字母转换为大写#defineUPCASE(c)(((c)>='a'&&(c)<='z')?((c)–0x20):(c))判断字符是不是10进值的数字#defineDECCHK(c)((c)>='0'&&(c)<='9')判断字符是不是16进值的数字#defineHEXCHK(c)(((c)>='0'&&(c)<='9')||((c)>='A'&&(c)<=' F')||((c)>='a'&&(c)<='f'))返回数组元素的个数#defineARR_SIZE(a)(sizeof((a))/sizeof(((a)[0])))。
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语言宏定义技巧(常用宏定义)
C语言宏定义技巧(常用宏定义)写好C语言,漂亮的宏定义很重要,使用宏定义可以防止出错,提高可移植性,可读性,方便性等等。
下面列举一些成熟软件中常用得宏定义。
1,防止一个头文件被重复包含#ifndef COMDEF_H#define COMDEF_H//头文件内容#endif2,重新定义一些类型,防止由于各种平台和编译器的不同,而产生的类型字节数差异,方便移植。
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 ) \/*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标准说明了五个预定义的宏名。
c中define的用法
c中define的用法c中define的用法的用法你知道吗?下面小编就跟你们详细介绍下c中define的用法的用法,希望对你们有用。
c中define的用法的用法如下:1、define--(无参数宏定义)用法一般形式为:#define标识符字符串(1)"#"表示其为预处理命令,凡是以"#"开头的都是预处理命令;"define"为宏定义命令;"标识符"为所定义的宏名;"字符串"可以是常数、表达式、字符串等。
(2)除了经常用到的如"#define MAXNUM 100"之外,还有其它多种灵活的用法,如"#define M (y*y+3*y)",注意,的表达式中()是必须的,否则在进行如"2*M+2"的运算时就会出现错误。
(3)末尾不需要分号(如果加分号,会连同分号一起代换)。
(4)define只是做简单的文本替换。
(5)作用域为宏定义开始,到源程序结束,终止定义域可用"#undef M".(6)宏名如果以字符串的形式被调用,则不做替换,如printf ("I M O")。
(7)可以嵌套进行定义,如#define PI 3.14#define S PI*R*R(8)习惯上把宏名写为大写的,以区别普通的变量。
2、define和typedef的区别define宏定义是在预处理完成的,typedef实在编译时处理的,typedef不是简单的代换,而是对类型说明符的重命名。
例如:#define P1 int*typedef int* P2;P1 a, b;//相当于int* a, b,此时a是int指针,b是int整数。
P2 a, b;//表示a和b都是int指针。
3、define(带参数宏定义)用法一般形式为:#define 宏名(形参)字符串最长见的 #define MAX(a,b)(a>b)?a:b(1)宏名和形参之间不能有空格。
c语言宏定义用法规则
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++中的宏定义(Macro definition)是一种预处理指令,用于在代码中定义宏。
宏定义使用#define关键字来指定标识符和其相应的替换文本。
在编译阶段,预处理器会将源代码中的宏使用其替换文本进行替换。
以下是C++中的宏定义规则:
1.宏定义的一般语法:
#define 标识符替换文本
2.标识符(Identifier):
o标识符可以是以字母或下划线开头,后续可以是字母、下划线或数字的组合。
o标识符不能是C++的关键字。
o标识符区分大小写。
3.替换文本(Replacement Text):
o替换文本可以包含任何有效的C++代码片段。
o替换文本可以使用宏定义中的参数。
o替换文本可以跨越多行,通过在行末使用反斜杠\进行延续。
4.宏定义的作用域:
o宏定义的作用域为从定义点开始,直到文件末尾或遇到相应的#undef指令。
o宏定义也可以在局部作用域内进行,例如在函数体
内部。
5.宏定义的注意事项:
o宏展开是简单的文本替换,不会进行类型检查或语法解析。
o在宏定义中出现的逗号,和分号;可能会与宏参数或周围的代码发生歧义,需要小心处理。
o宏定义中的括号可以避免一些因操作符优先级引起的问题。
另外,还有一些编码规范和最佳实践,可用于更好地使用宏定义,例如使用大写字母表示宏定义、用括号括起替换文本等。
需要注意的是,尽管宏定义在一些特定的情况下可以起到方便和灵活的作用,但过度使用宏定义可能会导致代码可读性变差和潜在的问题。
C语言#define用法总结
C语言#define用法总结黄海涛,2012-3-3如果你还在为使用#define而迷茫,那请阅读这篇文章;如果读完之后你还在迷茫,那请哪天心情好了,再回来读一遍。
:)欢迎跟着我的思路走……一、概述1、宏定义在C语言中,以#开头的为预处理命令。
定义形式:2、本质其本质是:使用宏定义中的字符串替换(Substitution)宏名。
这只是一种简单的代换,预处理程序对它不作任何检查。
如有错误,只能在编译已被宏展开后的源程序时发现。
3、替换时机预处理是指在进行编译的第一遍扫描(词法扫描和语法分析)之前所作的工作。
由预处理程序负责完成。
在源程序被编译之前,宏替换已经完成,其流程如下:源程序→预处理程序→预处理后的源程序→编译器4、作用域其作用域为宏定义命令起到源程序结束。
如要终止其作用域可使用# undef命令。
5、优缺点▲优点:宏定义使用得当,可以防止出错,提高可移植性,可读性等等;减少函数调用的开销。
▲缺点:可能存在参数副作用;展开后可能比函数调用开销更大。
※规则一:保证在宏替换之后不会发生错误。
二、无参宏定义1、定义的一般形式#define identifier token-sequence#define 标识符字符串2、简单常量●约束1:宏名通常采用易读大写字母表示。
●约束2:宏定义不是说明或语句,在行末不必加分号,如加上分号则连分号也一起替换。
●约束3:宏名在源程序中若用引号引起来,则预处理程序不对其作宏替换。
如:3、字符串为表达式※规则二:无参宏定义中字符串为表达式(即含有运算符),必须加小括号()。
可见,有括号与无括号差别很大,请小心加括号,保证展开后是你所期望的。
参考规则一。
4、5、6三、带参宏定义对带参数的宏,在调用中,不仅要宏展开,而且要用实参去代换形参。
1、带参宏定义的一般形式为:#define identifier(identifier-list) token-sequence#define 宏名(形参表) 字符串在字符串中含有各个形参,形参是标识符。
C语言宏定义详解
C语言宏定义详解转自:[url]/fengyu ruhui/archiv e/2007/08/16/1747090.aspx[/u rl]原作者不详1,防止一个头文件被重复包含#ifndef COMDEF_H#define COMDEF_H//头文件内容#endif2,重新定义一些类型,防止由于各种平台和编译器的不同,而产生的类型字节数差异,方便移植。
typede f unsign ed char boolea n; /* Boolea n valuetype. */typede f unsign ed long int uint32; /* Unsign ed 32 bit value*/typede f unsign ed short uint16; /* Unsign ed 16 bit value*/typede f unsign ed char uint8; /* Unsign ed 8 bit value*/typede f signed long int int32; /* Signed 32 bit value*/typede f signed short int16; /* Signed 16 bit value*/typede f signed char int8; /* Signed 8 bit value*///下面的不建议使用typede f unsign ed char byte; /* Unsign ed 8 bit valuetype. */typede f unsign ed short word; /* Unsing ed 16 bit valuetype. */typede f unsign ed long dword; /* Unsign ed 32 bit valuetype. */typede f unsign ed char uint1; /* Unsign ed 8 bit valuetype. */typede f unsign ed short uint2; /* Unsign ed 16 bit valuetype. */typede f unsign ed long uint4; /* Unsign ed 32 bit valuetype. */typede f signed char int1; /* Signed 8 bit valuetype. */typede f signed short int2; /* Signed 16 bit valuetype. */typede f long int int4; /* Signed 32 bit valuetype. */typede f signed long sint31; /* Signed 32 bit value*/typede f signed short sint15; /* Signed 16 bit value*/typede f 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,得到一个fi eld在结构体(struct)中的偏移量#define FPOS( type, field) \/*lint -e545 */ ( (dword) &(( type *) 0)-> field) /*lint +e545 */6,得到一个结构体中fie ld所占用的字节数#define FSIZ( type, field) sizeof( ((type *) 0)->field)7,按照LSB格式把两个字节转化为一个Word#define FLIPW( ray ) ( (((word) (ray)[0]) * 256) + (ray)[1] )8,按照LSB格式把一个W ord转化为两个字节#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_L O(xxx) ((byte) ((word)(xxx) & 255))#define WORD_H I(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_SA T( val ) (val = ((val)+1 > (val)) ? (val)+1 : (val))16,返回数组元素的个数#define ARR_SI ZE( a ) ( sizeof( (a) ) / sizeof( (a[0]) ) )17,返回一个无符号数n尾的值MOD_BY_PO WER_O F_TWO(X,n)=X%(2^n) #define MOD_BY_POWE R_OF_TWO( val, mod_by ) \( (dword)(val) & (dword)((mod_by)-1) )18,对于IO空间映射在存储空间的结构,输入输出处理#define inp(port) (*((volati le byte *) (port)))#define inpw(port) (*((volati le word *) (port)))#define inpdw(port) (*((volati le dword*)(port)))#define outp(port, val) (*((volati le byte *) (port)) = ((byte) (val)))#define outpw(port, val) (*((volati le word *) (port)) = ((word) (val)))#define outpdw(port, val) (*((volati le dword*) (port)) = ((dword) (val)))19,使用一些宏跟踪调试A N S I标准说明了五个预定义的宏名。
c中各类宏定义的用法
假设a.h内容如下:#ifndef AH#define AHtypedef int INT;#endifb.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 AHtypedef int INT;#endif#ifndef AH#define AHtypedef int INT;#endifmain(){INT a;}这样的话,因为程序中已经定义了一次AH,所以不会走到第二次声明INT的分支。
所以不会出错。
#ifndef #define #endif的用法整理:shichenghua/blog/?56085/action_viewspace_itemid_1145.htm l(前段时间要到这个,感觉shichenghua整理得不错,所以收藏到此处,若不同意,随时可以撤下谢谢shichenghua)文件中的#ifndef头件的中的#ifndef,这是一个很关键的东西。
比如你有两个C文件,这两个C文件都include了同一个头文件。
而编译时,这两个C文件要一同编译成一个可运行文件,于是问题来了,大量的声明冲突。
还是把头文件的内容都放在#ifndef和#endif中吧。
不管你的头文件会不会被多个文件引用,你都要加上这个。
一般格式是这样的:#ifndef <标识>#define <标识>............#endif<标识>在理论上来说可以是自由命名的,但每个头文件的这个“标识”都应该是唯一的。
c语言宏定义的语法要求
c语言宏定义的语法要求在C语言中,宏定义是使用`#define`关键字进行的。
宏定义用于在程序中创建符号常量、函数宏和条件编译等。
以下是宏定义的语法要求:1. 符号常量的宏定义:```c#define IDENTIFIER value```- `IDENTIFIER` 是你为常量定义的名称。
- `value` 是该常量的值。
示例:```c#define PI 3.14159```2. 函数宏的宏定义:```c#define MACRO_NAME(parameters) replacement```- `MACRO_NAME` 是你为函数宏定义的名称。
- `(parameters)` 是函数宏的参数列表。
- `replacement` 是用于替换宏调用的代码。
示例:```c#define SQUARE(x) ((x) * (x))```3. 多行宏定义:```c#define MACRO_NAME \statement1; \statement2;```4. 条件编译宏定义:```c#ifdef MACRO_NAME// 代码块1#else// 代码块2#endif```5. 字符串化运算符:```c#define STRINGIZE(x) #x```这个宏允许你将传递给它的参数转换为字符串。
例如:```c#define HELLO_WORLD_STRING STRINGIZE(Hello World)```在上述例子中,`HELLO_WORLD_STRING` 将被替换为字符串"Hello World"。
6. 连接运算符:```c#define CONCATENATE(x, y) x ## y```这个宏允许你连接两个标识符。
例如:```cint xy = CONCATENATE(3, 4); // 将被替换为int xy = 34;```以上是宏定义的一些基本语法要求。
请注意,使用宏时要小心,确保在宏定义中使用括号来确保优先级正确。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
假设a.h内容如下:#ifndef AH#define AHtypedef int INT;#endifb.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 AHtypedef int INT;#endif#ifndef AH#define AHtypedef int INT;#endifmain(){INT a;}这样的话,因为程序中已经定义了一次AH,所以不会走到第二次声明INT的分支。
所以不会出错。
#ifndef #define #endif的用法整理:shichenghua/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_......#endif2.在#ifndef中定义变量出现的问题(一般不定义在#ifndef中)。
#ifndef AAA#define AAA...int i;...#endif里面有一个变量定义在vc中链接时就出现了i重复定义的错误,而在c中成功编译。
结论:(1).当你第一个使用这个头的.cpp文件生成.obj的时候,int i 在里面定义了当另外一个使用这个的.cpp再次[单独]生成.obj的时候,int i 又被定义然后两个obj被另外一个.cpp也include 这个头的,连接在一起,就会出现重复定义.(2).把源程序文件扩展名改成.c后,VC按照C语言的语法对源程序进行编译,而不是C++。
在C语言中,若是遇到多个int i,则自动认为其中一个是定义,其他的是声明。
(3).C语言和C++语言连接结果不同,可能(猜测)时在进行编译的时候,C++语言将全局变量默认为强符号,所以连接出错。
C语言则依照是否初始化进行强弱的判断的。
(参考)解决方法:(1).把源程序文件扩展名改成.c。
(2).推荐解决方案:.h中只声明extern int i;在.cpp中定义<x.h>#ifndef __X_H__#define __X_H__extern int i;#endif //__X_H__<x.c>int i;注意问题:(1).变量一般不要定义在.h文件中。
一般情况下,源程序中所有的行都参加编译。
但是有时希望对其中一部分内容只在满足一定条件才进行编译,也就是对一部分内容指定编译的条件,这就是“条件编译”。
有时,希望当满足某条件时对一组语句进行编译,而当条件不满足时则编译另一组语句。
条件编译命令最常见的形式为:#ifdef 标识符程序段1#else程序段2#endif它的作用是:当标识符已经被定义过(一般是用#define命令定义),则对程序段1进行编译,否则编译程序段2。
其中#else部分也可以没有,即:#ifdef程序段1#denif这里的“程序段”可以是语句组,也可以是命令行。
这种条件编译可以提高C源程序的通用性。
如果一个C源程序在不同计算机系统上系统上运行,而不同的计算机又有一定的差异。
例如,我们有一个数据类型,在Windows平台中,应该使用long类型表示,而在其他平台应该使用float表示,这样往往需要对源程序作必要的修改,这就降低了程序的通用性。
可以用以下的条件编译:#ifdef WINDOWS#define MYTYPE long#else#define MYTYPE float#endif如果在Windows上编译程序,则可以在程序的开始加上#define WINDOWS这样则编译下面的命令行:#define MYTYPE long如果在这组条件编译命令之前曾出现以下命令行:#define WINDOWS 0则预编译后程序中的MYTYPE都用float代替。
这样,源程序可以不必作任何修改就可以用于不同类型的计算机系统。
当然以上介绍的只是一种简单的情况,可以根据此思路设瞥?a href="javascript:;" onClick="tagshow(event, '%C6%E4%CB%FC');return false;">其它的条件编译?例如,在调试程序时,常常希望输出一些所需的信息,而在调试完成后不再输出这些信息。
可以在源程序中插入以下的条件编译段:#ifdef DEBUGprint ("device_open(%p) ", file);#endif如果在它的前面有以下命令行:#define DEBUG则在程序运行时输出file指针的值,以便调试分析。
调试完成后只需将这个define命令行删除即可。
有人可能觉得不用条件编译也可达此目的,即在调试时加一批printf语句,调试后一一将printf语句删除去。
的确,这是可以的。
但是,当调试时加的printf语句比较多时,修改的工作量是很大的。
用条件编译,则不必一一删改printf语句,只需删除前面的一条“#define DEBUG”命令即可,这时所有的用DEBUG作标识符的条件编译段都使其中的printf语句不起作用,即起统一控制的作用,如同一个“开关”一样。
有时也采用下面的形式:#ifndef 标识符程序段1#else程序段2#endif只是第一行与第一种形式不同:将“ifdef”改为“ifndef”。
它的作用是:若标识符未被定义则编译程序段1,否则编译程序段2。
这种形式与第一种形式的作用相反。
以上两种形式用法差不多,根据需要任选一种,视方便而定。
还有一种形式,就是#if后面的是一个表达式,而不是一个简单的标识符:#if 表达式程序段1#else程序段2#endif它的作用是:当指定的表达式值为真(非零)时就编译程序段1,否则编译程序段2。
可以事先给定一定条件,使程序在不同的条件下执行不同的功能。
作用范围就是当前文件啊。
因为编译是以cpp或c文件位单位的嘛。
还以这个为例://正常代码#ifdef _DEBUGTRACE("Some infomation");#else//Now is release version,so do nothing#endif//正常代码编译时是先把所有的预编译处理展开(比如宏)再编译,所以Debug 模式下,编译时的代码是://正常代码TRACE("Some infomation");//正常代码Release模式下的代码是://正常代码//正常代码------------------------------------------------------------------------------------------------今天整理了一些#define的用法,与大家共享!1.简单的define定义#define MAXTIME 1000一个简单的MAXTIME就定义好了,它代表1000,如果在程序里面写if(i编译器在处理这个代码之前会对MAXTIME进行处理替换为1000。
这样的定义看起来类似于普通的常量定义C++(C++培训)ONST,但也有着不同,因为define 的定义更像是简单的文本替换,而不是作为一个量来使用,这个问题在下面反映的尤为突出。
2.define的“函数定义”define可以像函数那样接受一些参数,如下#define max(x,y) (x)>(y)?(x):(y);这个定义就将返回两个数中较大的那个,看到了吗?因为这个“函数”没有类型检查,就好像一个函数模板似的,当然,它绝对没有模板那么安全就是了。
可以作为一个简单的模板来使用而已。
但是这样做的话存在隐患,例子如下:#define Add(a,b) a+b;在一般使用的时候是没有问题的,但是如果遇到如:c * Add(a,b) * d的时候就会出现问题,代数式的本意是a+b然后去和c,d相乘,但是因为使用了define(它只是一个简单的替换),所以式子实际上变成了c*a + b*d另外举一个例子:#define pin (int*);pin a,b;本意是a和b都是int型指针,但是实际上变成int* a,b;a是int型指针,而b是int型变量。
这是应该使用typedef来代替define,这样a和b就都是int型指针了。
所以我们在定义的时候,养成一个良好的习惯,建议所有的层次都要加括号。
3.宏的单行定义#define A(x) T_##x#define B(x) #@x#define C(x) #x我们假设:x=1,则有:A(1)------〉T_1B(1)------〉’1’C(1)------〉\"1\"(这里参考了hustli的文章)4.define的多行定义define可以替代多行的代码,例如MFC中的宏定义(非常的经典,虽然让人看了恶心)#define MACRO(arg1, arg2) do { \\/* declarations */ \\stmt1; \\stmt2; \\/* ... */ \\} while(0) /* (no trailing ; ) */关键是要在每一个换行的时候加上一个\"\\\"摘抄自/user1/16293/archives/2005/115370.shtml 修补了几个bug 5.在大规模的开发过程中,特别是跨平台和系统的软件里,define最重要的功能是条件编译。