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

合集下载

define 宏定义函数用法

define 宏定义函数用法

宏定义函数在C语言中通常使用#define预处理指令来定义。

宏定义函数允许你创建简单的函数,这些函数在编译时被预处理器替换为相应的代码。

以下是宏定义函数的几个常见用法:1、定义简单的替换:c复制代码#define SQUARE(x) ((x) * (x))使用这个宏,你可以这样写代码:c复制代码int result = SQUARE(5); // 这将被替换为int result = ((5) * (5));2、使用参数:c复制代码#define MAX(a, b) ((a) > (b) ? (a) : (b))使用这个宏,你可以这样写代码:c复制代码int max_val = MAX(3, 7); // 这将被替换为int max_val = ((3) > (7) ? (3) : (7));3、避免重复计算:考虑以下情况,你可能想要避免重复计算一个值:cint a = some_complex_function();int b = another_complex_function(a);int c = yet_another_complex_function(a);你可以使用宏来避免重复计算:c#define COMPLEX_VALUE some_complex_function()然后在其他地方使用COMPLEX_VALUE代替some_complex_function()的调用。

但请注意,这样做可能会使代码更难理解,并且在某些情况下可能会导致错误(例如,当some_complex_function()的行为取决于上下文时)。

因此,应该谨慎使用这种方法。

4、调试和跟踪:使用宏可以方便地插入调试或跟踪代码。

例如,你可以定义一个宏来打印变量的值:c#define PRINT_VAR(x) printf(#x " = %d\n", x)然后在代码中使用这个宏:cint a = 5;PRINT_VAR(a); // 这将被替换为printf("a = %d\n", a);,从而打印出"a = 5"5、条件编译:你可以使用#if、#ifdef、#ifndef等预处理指令与宏结合使用,以根据不同的条件包含或排除代码段。

C语言中define的用法

C语言中define的用法

C语言中define的用法在C语言中,#define 是一个预处理指令,用于定义常量、宏或函数。

它告诉编译器在程序编译之前进行某些特定的替换或操作。

以下是 #define 的几种常见用法:1.定义常量使用 #define 可以定义常量,这样可以使代码更具可读性并减少错误。

c复制代码#define PI 3.14159#define MAX_SIZE 100在程序中,每当使用 PI 或 MAX_SIZE 时,它们都会被替换为其定义的值。

2. 定义宏宏是一个简单的替换操作。

当预处理器遇到宏时,它会用宏的定义替换它。

c复制代码#define SQUARE(x) ((x) * (x))当你使用 SQUARE(5) 时,预处理器会将其替换为 ((5) * (5))。

注意:宏可能会引入一些意外的副作用,尤其是当参数被多次评估时。

例如,上面的 SQUARE 宏在 SQUARE(a++) 中会评估 a 两次,导致 a 增加两次。

为了避免这种情况,你可以使用 #define SQUARE(x) (((x) * ((x))) 来确保 x 只被评估一次。

3. 定义函数式宏函数式宏允许你定义更复杂的宏,它们可以像函数一样接受参数并执行操作。

c复制代码#define MAX(a, b) (((a) > (b)) ? (a) : (b))虽然这看起来像一个函数,但实际上它是一个宏。

这意味着它在预处理阶段进行替换,而不是在运行时。

4. 条件编译#define 还可以与预处理器指令(如 #if, #ifdef, #ifndef, #else, #elif, 和 #endif)结合使用,以实现条件编译。

c复制代码#define FEATURE_A#ifdef FEATURE_A// 这部分代码只有在定义了FEATURE_A时才会被编译#else// 这部分代码只有在没有定义FEATURE_A时才会被编译#endif使用 #define 时,请确保你了解其工作原理和潜在的风险,以避免在代码中出现难以追踪的错误。

define宏定义 条件

define宏定义 条件

define宏定义条件
宏定义是一种在编程语言中用来创建符号名称的预处理指令。

通过宏定义,可以将一个标识符与一个特定的字符串或者代码片段
关联起来,从而可以在程序中使用这个标识符来代表对应的字符串
或代码片段。

在C、C++、Java等编程语言中,宏定义通常使用
#define关键字来声明。

宏定义可以用于定义常量、函数、代码片段等,以便在程序中
进行重复使用。

例如,可以使用宏定义来声明常量,如#define PI 3.14159,这样在程序中就可以直接使用PI来代表 3.14159。

此外,宏定义还可以用于简化代码,比如定义一个函数宏来实现特定的功能,从而减少重复的代码编写。

另外,条件宏定义是指在宏定义中使用条件语句,根据不同的
条件来定义不同的宏。

条件宏定义通常使用#ifdef、#ifndef、#if、#else等预处理指令来实现条件判断,根据条件的真假来定义或者
取消定义相应的宏。

这样可以根据不同的条件来控制程序中不同部
分的编译行为,从而实现更灵活的代码编写。

总之,宏定义是一种在程序中用来创建符号名称的机制,可以
用于定义常量、函数、代码片段等,而条件宏定义则是在宏定义中加入条件判断,以实现根据不同条件来定义不同的宏的功能。

这样可以使程序更加灵活和可维护。

c语言宏定义的符号用法

c语言宏定义的符号用法

c语言宏定义的符号用法在C语言中,宏定义是一种非常有用的预处理指令,它允许我们在编译时对代码进行替换。

宏定义可以帮助我们简化代码,提高代码的可读性和可维护性。

然而,正确地使用宏定义需要了解一些符号用法,下面我们将详细介绍这些符号用法。

一、宏定义的基本语法在C语言中,宏定义的一般语法如下:```c#define宏名(参数列表)替换文本```其中,宏名是用户自定义的名称,参数列表是可选的,用于指定宏的参数。

替换文本是在编译时将被替换为实际代码的文本。

二、符号用法1.宏展开与预处理指令的位置:宏定义通常位于源代码的顶部,例如在头文件中或在主程序文件的开头。

在预处理阶段,宏将被替换为实际的代码。

因此,在使用宏之前,需要确保宏的定义在代码中是可见的。

2.宏参数的使用:宏参数可以是任何有效的C语言表达式,包括变量、常量、函数调用等。

在使用宏时,需要将参数用括号括起来,以确保参数的求值顺序正确。

此外,需要确保参数的类型与替换文本的类型匹配。

3.宏的嵌套:宏可以嵌套定义,即在宏内部定义另一个宏。

这种用法可以提高代码的可读性和可维护性。

但是,需要注意避免无限嵌套,以防止出现死循环。

4.宏的可见性:宏定义通常是在头文件中定义的,因此需要在包含该头文件的源文件中可见。

如果需要在多个源文件中使用相同的宏定义,可以将宏定义放在公共头文件中,并在需要使用的源文件中包含该头文件。

5.宏的副作用:宏替换是在预处理阶段进行的,因此宏定义可能会产生一些副作用,例如修改全局变量或引入新的依赖关系。

在使用宏时,需要仔细考虑其副作用,并确保代码的正确性和稳定性。

6.避免使用不确定的表达式:在使用宏时,应避免使用不确定的表达式或难以预测的结果。

否则,可能会导致编译错误或不可预期的行为。

7.保留字的使用:在使用宏时,需要特别注意保留字的使用。

由于预处理器会将宏名展开为实际的代码,因此使用保留字作为宏名可能会导致意外的结果或错误。

建议使用描述性名称作为宏名,以避免混淆和错误。

verilog中define用法

verilog中define用法

verilog中define用法一、概述Verilog是一种用于描述数字电路和系统的硬件描述语言。

在Verilog中,define是一种预处理指令,用于定义常量或宏。

通过使用define,可以在代码中方便地重用和修改常量或表达式,从而提高代码的可读性和可维护性。

二、define用法Verilog中的define用法非常简单,只需要在代码中插入define关键字,后面跟着要定义的常量或宏的名称和值即可。

1. 定义常量:可以使用define来定义常量,其语法如下:define constant_name value例如:define CLK_FREQ 10MHz2. 定义宏:可以使用define来定义宏,其语法如下:define macro_name(argument) macro_body或者define macro_name macro_body其中,argument是可选的参数列表,macro_body是宏体的代码。

例如:define ADD(a, b) (a + b)或者直接使用define来定义一个简单的加法宏:define ADD(a, b) (a + b) macro_add(a, b)3. 使用define定义的常量或宏:在代码中可以使用define定义的常量或宏,其语法如下:constant_name或macro_name variable_name = value例如:clk = CLK_FREQ; // 使用定义的CLK_FREQ常量作为时钟频率delay = macro_add(1ns, 500ps); // 使用定义的ADD宏计算延迟时间三、注意事项1. 宏定义中的参数可以是任意表达式,但不能包含未定义的变量或常量。

2. 宏定义中的代码块必须用大括号{}括起来,以确保代码块的正确执行。

3. 在使用define定义的常量或宏时,必须使用正确的语法格式,否则会出现编译错误。

4. 在使用define定义的常量或宏时,应注意避免与系统级变量或函数名称冲突,以免引起混淆和错误。

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允许这样作,在类函数宏的替换部分,#符号用作一个预处理运算符,它可以把语言符号转化程字符串。

define宏定义函数

define宏定义函数

define宏定义函数宏定义是C/C++语言中一种预处理指令,可以用来对代码中的固定值或者复杂表达式进行替换,减少代码编写时的重复性问题,提高代码重用性和可读性。

宏定义的语法格式为:#define 宏名称宏替换文本其中,宏名称是自定义的标识符,宏替换文本可以是单个字符、数值、表达式、函数调用等。

宏定义的有效范围是从定义处到文件末尾或者遇到#undef指令为止。

宏定义的优点在于,它可以让程序员在代码中使用一个短小的名称来代替一个复杂的表达式或者语句,从而提高代码可读性和可维护性。

同时,在编译时,编译器会将所有使用到宏定义的代码中的宏名称展开成对应的宏替换文本,从而使得程序的运行效率得到提高。

宏定义的应用场景非常广泛,例如:1.定义常量:可以使用#define宏定义,将一个固定的值定义为一个常量,方便在代码中多次使用。

例如:#define PI 3.14这样在后续的代码中就可以使用PI来代替3.14,提高可读性和可维护性。

2.定义函数:宏定义可以定义一些简单的函数。

例如:#define max(a,b) ((a)>(b)?(a):(b))这个宏定义表示求取两个数中的最大值,在后续的代码中可以用max(a,b)来代替((a)>(b)?(a):(b)),达到简洁、明了的效果。

3.定义缩写:在代码中,有时需要使用一些比较长的名称来表示一些事物,为了方便使用,可以用宏定义来缩写这些名称,在代码中使用时可以提高可读性和代码规范性。

例如:#define HTTP_STATUS_OK 200#define HTTP_STATUS_BAD_REQUEST 4004.条件编译:宏定义可以用于条件编译,在程序中加入一些特别的代码,根据不同的编译选项选择编译或者不编译这些代码。

例如:#ifdef DEBUGprintf("error message: %s\n", error_msg);#endif如果在编译程序的时候加上了-DDEBUG选项,则会将上述代码编译到程序中,否则会被忽略。

宏定义中##和#的作用

宏定义中##和#的作用
例如:
> #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)来

宏定义define用法

宏定义define用法

宏定义define用法好的,以下是为您创作的关于【宏定义 define 用法】的科普文章:在编程的奇妙世界里,有一个非常有用的工具,叫做“宏定义(define)”。

咱们可以把宏定义想象成一个神奇的“魔法标签”。

比如说,你有一个经常会用到的数字,像是 50 ,每次写代码都要写这个数字,是不是有点麻烦?这时候宏定义就派上用场啦!你可以给 50 贴上一个标签,比如叫“MAX_NUMBER” 。

之后在代码里,只要提到“MAX_NUMBER” ,就相当于提到了 50 。

那宏定义具体是怎么回事呢?简单来说,宏定义就是用一个标识符来代表一个字符串或者一个值。

它就像是给某个东西起了一个简单易记的别名。

在 C 或 C++ 等编程语言中,我们使用“#define”这个关键字来创建宏定义。

比如说,“#define PI 3.14159” ,这就表示以后在代码里看到“PI” ,就代表了 3.14159 这个值。

宏定义在实际应用中可太有用啦!假设我们正在写一个计算圆形面积的程序,每次都要输入 3.14159 来计算圆周率,不仅容易出错,还很繁琐。

但有了宏定义,直接用“PI”,清晰又方便,还不容易出错。

再比如说,我们要在一个程序里处理不同的单位转换。

假设我们经常要把厘米转换为米,我们可以定义一个宏“#define CM_TO_M 0.01” ,这样在代码中进行单位转换的时候,直接使用这个宏,代码简洁明了,可读性大大提高。

宏定义还能用来定义一些字符串常量呢。

比如“#define GREETING "Hello, World!"” ,然后在需要输出这个问候语的地方,直接使用“GREETING” 就可以啦。

但是,使用宏定义也得小心一些小“陷阱”。

因为宏定义只是简单的文本替换,有时候可能会出现一些意想不到的结果。

比如说,如果宏定义的表达式比较复杂,可能会导致计算顺序不符合预期。

另外,宏定义在整个代码文件中都是有效的,不像变量有特定的作用域。

C语言中define的用法

C语言中define的用法

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

宏是一种预处理方法,它可以将一些常用的代码片段封装成一个宏,并在程序编译前将它们展开,以便于复用和代码的可维护性。

宏定义的语法格式为:#define 宏名(value) 代码块,其中宏名是一个标识符,用于表示宏的名称,而value是一个可选的参数,用于定义宏的值。

代码块是宏的执行体,它可以是任何合法的C语句或表达式。

在C语言程序中,宏定义通常放置在文件的开头或外部头文件中。

它的作用范围是从定义处到程序的结束或者直到另一个#undef指令出现为止。

使用宏定义可以提高代码的可读性和可维护性,同时还可以使程序更加具有通用性和灵活性。

但是宏定义也有一些缺点,比如代码的可读性和调试性较差,并且容易造成代码冗余和不必要的开销。

总之,在C语言中,宏定义是一个非常常用的预处理方法,它可以帮助程序员编写更加简洁、高效和灵活的代码。

#ifndef,#define,#endif作用

#ifndef,#define,#endif作用

#ifndef,#define,#endif作⽤#ifndef 它是if not define 的简写,是宏定义的⼀种,实际上确切的说,这应该是预处理功能三种(宏定义、⽂件包含、条件编译)中的⼀种----条件编译。

在c语⾔中,对同⼀个变量或者函数进⾏多次声明是不会报错的。

所以如果h⽂件⾥只是进⾏了声明⼯作,即使不使⽤# ifndef宏定义,多个c⽂件包含同⼀个h⽂件也不会报错。

但是在c++语⾔中,#ifdef的作⽤域只是在单个⽂件中。

所以如果h⽂件⾥定义了全局变量,即使采⽤#ifdef宏定义,多个c⽂件包含同⼀个h⽂件还是会出现全局变量重定义的错误。

使⽤#ifndef可以避免下⾯这种错误:如果在h⽂件中定义了全局变量,⼀个c⽂件包含同⼀个h⽂件多次,如果不加#ifndef宏定义,会出现变量重复定义的错误;如果加了#ifndef,则不会出现这种错误。

⽰例:#ifndef x //先测试x是否被宏定义过#define x程序段1blabla~ //如果x没有被宏定义过,定义x,并编译程序段 1#endif 程序段2blabla~ //如果x已经定义过了则编译程序段2的语句,“忽视”程序段 1 条件指⽰符#ifndef 的最主要⽬的是防⽌头⽂件的重复包含和编译。

了解:条件编译当然也可以⽤条件语句来实现。

但是⽤条件语句将会对整个源程序进⾏编译,⽣成的⽬标程序程序很长,⽽采⽤条件编译,则根据条件只编译其中的程序段1或程序段2,⽣成的⽬标程序较短。

如果条件选择的程序段很长,采⽤条件编译的⽅法是⼗分必要的。

#ifndef 和 #endif 要⼀起使⽤,如果丢失#endif,可能会报错。

总结⼀下:在c语⾔中,对同⼀个或者函数进⾏多次声明是不会报错的。

所以如果h⽂件⾥只是进⾏了声明⼯作,即使不使⽤# ifndef,⼀个c⽂件多次包含同⼀个h⽂件也不会报错。

 使⽤#ifndef可以避免下⾯这种错误:如果在h⽂件中定义了,⼀个c⽂件包含同⼀个h⽂件多次,如果不加#ifndef,会出现变量重复定义的错误;如果加了#ifndef,则不会出现这种错.#ifdef 与ifndef类似,ifdef顾名思义,就是if define,看例⼦#ifdef x程序1blabla~#endif 翻译:如果宏定义了x,则执⾏程序1. 此外,还有其他形式,还是看例⼦好些:#ifndef x#define x程序段1#else程序段2#endif 当x没有由#define定义过,则编译“程序段1”,否则编译“程序段2”。

宏定义#define详解

宏定义#define详解

宏定义#define详解1. #define主要功能c语⾔中⽤到很多宏定义,为了头⽂件被重复⽤到#ifndef #define,#ifdefine edfif等条件编译宏不是语句,结尾不⽤加“;”,否则会被替换进进程中#表⽰这是⼀条预处理指令如果写宏不⽌⼀⾏,则在结尾加反斜杠使多⾏能连接上,但第⼆⾏要对齐,否则空格也会作为替换⽂本的⼀部分 2.⽆参宏⽆参宏即宏名之后不带参数,只是简单的⽂本替换#define与typedef区别两者都可以表⽰数据类型1#define INIT1 int 2 typedef in UINT2但有时候也会有区别⽐如定义指针类型的变量时1#define INT1 int *2 typedef int * INT2;3 INT1 a1, b1;4 INT2 a2, b2;INT1 a1,b1;被替换后为 int *a1,b1;即⼀个指向int类型的指针⼀个int类型的变量INT2 a2,b2;则是两个指向int类型的指针3.有参宏带参数的宏定义,宏名中不能有空格,宏名与形参表之间也不能有空格,⽽形参表中形参之间可以有空格有参宏实现⼀个数的平⽅1#define COUNT(M) M*M2int x=6;3 print(COUNT(x+1));4 print(COUNT(++X));5结果输出:13和56⽽不是函数的输出49和原因在于预编译器不进⾏技术,只是进⾏简单的⽂本替换,COUNT(x+1)被替换成COUNT(x+1*x+1)CUNT(++x)被替换成++x*++x即为7*8=56⽽不是想要的7*7=49,连续前置⾃加加两次解决办法是⽤括号将整个替换⽂本及每个参数⽤括号括起来但即便是加上括号也不能解决第⼆种情况,所以解决办法是尽量不使⽤++,-等符号函数实现⼀个数的平⽅1int count(int x)2 {3return x*x4 }有参宏与函数区别在宏定义#define COUNT(M) M*M中的形参不分配内存单元,不做类型定义,只是简单的⽂本替换,⽽函数int count(intx)中形参x是局部变量,会在栈区分配内存单元,所以要做类型定义,⽽且实参与形参之间是值传递。

带参数的宏定义#define

带参数的宏定义#define

9.1.2 带参数的宏定义带参数的宏定义的一般形式如下:#define <宏名>(<参数表>) <宏体>其中, <宏名>是一个标识符,<参数表>中的参数可以是一个,也可以是多个,视具体情况而定,当有多个参数的时候,每个参数之间用逗号分隔。

<宏体>是被替换用的字符串,宏体中的字符串是由参数表中的各个参数组成的表达式。

例如:#define SUB(a,b) a-b如果在程序中出现如下语句:result=SUB(2, 3)则被替换为:result=2-3;如果程序中出现如下语句:result= SUB(x+1, y+2);则被替换为:result=x+1-y+2;在这样的宏替换过程中,其实只是将参数表中的参数代入到宏体的表达式中去,上述例子中,即是将表达式中的a和b分别用2和3代入。

我们可以发现:带参的宏定义与函数类似。

如果我们把宏定义时出现的参数视为形参,而在程序中引用宏定义时出现的参数视为实参。

那么上例中的a和b就是形参,而2和3以及x+1和y+2都为实参。

在宏替换时,就是用实参来替换<宏体>中的形参。

下面是带参数的宏定义的例子:例9-4#include <iostream.h>#define SUB(a,b) a-bvoid main (){int x,y,result;x=2;y=3;result=SUB(x+2,y-1);cout<< "result="<<result<<end1;}该程序经宏替换后,main函数变为:void main (){int x,y,result;result=x+2-y-1;cout<< "result="<<result<<end1;}执行该程序后,输出结果如下:result=0虽然带参数的宏定义和带参数的函数很相似,但它们还是有本质上的区别:(1)在带参的宏定义中,形式参数不是变量,只是一个符号,不分配内存单元,不必定义其形式参数的类型。

c中define的用法

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)宏名和形参之间不能有空格。

defined在c语言中用法

defined在c语言中用法

defined在c语言中用法在C语言中,"defined"是一个预处理指令,用于在编译阶段判断一个常量、宏定义或者条件是否已经被定义。

它的使用格式为:```#if defined(常量名或宏名)// 执行某些代码#endif```"defined"的存在使得我们能够根据程序的运行环境来选择性地编译或执行某些代码,从而提高程序的灵活性和可移植性。

"defined"主要用法有以下几种:一、判断常量是否已定义在C语言中,我们可以使用宏定义来声明常量,例如:```c#define PI 3.14159```如果我们想要在代码中根据常量PI的定义来执行不同的操作,可以使用"defined"来判断常量是否已定义,如下:```c#if defined(PI)// 执行相关代码#endif```这样,当常量PI被定义时,相关代码会被执行;如果没有定义PI,则不会执行。

二、判断宏是否已定义除了判断常量是否已定义,"defined"也可以用来判断宏是否已经定义。

在C语言中,宏定义是通过预处理指令#define来定义的。

如果我们需要根据宏是否已定义来进行不同的编译操作,可以使用以下格式:```c#if defined(宏名)// 执行相关代码#endif```例如,如果我们定义了一个名为DEBUG的宏,可以使用"defined"来判断宏是否已经定义,从而根据需要执行调试代码:```c#if defined(DEBUG)// 执行调试代码#endif```三、条件编译"defined"还可以用于条件编译,即根据宏的定义情况编译不同的代码块。

例如,我们可以根据不同的操作系统来编译不同的代码段:```c#if defined(WIN32)// Windows平台下的代码#elif defined(LINUX)// Linux平台下的代码#elif defined(MAC)// Mac平台下的代码#else// 默认的代码#endif```在上述示例中,根据不同的宏定义情况,编译器会选择相应的代码块进行编译。

verilogdefine用法

verilogdefine用法

Verilogdefine用法1.引言在V er il o g中,`de f in e指令是一种宏定义方式,可以用于定义常量、函数等等。

它使得在设计过程中可以进行常量替换,提高了代码的可读性和可维护性。

本文将介绍`d ef in e指令的用法,以帮助读者更好地理解和使用V er il og语言。

2. `d efine指令的基本语法在V er il og中,`d ef i ne指令的语法格式如下所示:`d ef in e宏名称宏取值其中,`de fi ne为指令关键字,宏名称表示需要定义的宏名称,宏取值表示宏的取值。

3.定义常量`d ef in e指令最常用的功能是定义常量。

通过定义常量,可以在代码中使用宏名称进行替换,从而实现代码的简洁和易读。

下面是一个常量定义的示例:`d ef in eW ID TH8在上述示例中,我们定义了一个名为`W I DT H`的常量,它的取值为8。

在代码中,可以通过`W ID TH来表示8这个值。

4.定义带参数的宏除了定义常量外,`d e fi ne指令还可以定义带参数的宏,从而实现更灵活的代码替换。

下面是一个带参数的宏定义的示例:`d ef in eA DD(a,b)(a+b)在上述示例中,我们定义了一个名为`ADD`的宏,它接受两个参数a和b,并返回其和。

在使用时,可以通过`A DD(a,b)来替换成(a+b)这个表达式。

5.宏的作用范围在V er il og中,`d ef i ne指令定义的宏在整个代码中都是有效的,即具有全局作用域。

这意味着无论在哪个模块中都可以使用这个宏。

下面是一个使用宏的示例:m o du le My Mo du le(in p ut[`WI DT H-1:0]a,ou tp ut[`WI DT H-1:0]b);//使用宏定义的常量r e g[`W ID TH-1:0]te m p;i n it ia lb eg int e mp=`WI DT H;$d is pl ay("常量值为:%d",te mp);e n d//使用宏定义的带参数宏r e g[`W ID TH-1:0]su m;i n it ia lb eg ins u m=`A DD(a,b);$d is pl ay("两数之和为:%d",s um);e n de n dm od ul e在上述示例中,我们在一个模块中使用了`W ID TH这个宏定义的常量,并且使用了`AD D这个宏定义的带参数宏。

C语言宏定义#define的理解与资料梳理

C语言宏定义#define的理解与资料梳理

C语言宏定义#define的理解与资料梳理define函数定义一个常量。

为帮助大家更好地理解这个内容,以下是百分网小编搜索整理的关于C语言宏定义#define的理解与资料梳理,供参考借鉴,希望对各位老师有所帮助!想了解更多相关信息请持续关注我们应届毕业生考试网!1、利用define来定义数值宏常量#define宏定义是个演技非常高超的替身演员,但也会经常耍大牌的,所以我们用它要慎之又慎。

它可以出现在代码的任何地方,从本行宏定义开始,以后的代码就就都认识这个宏了;也可以把任何东西定义成宏。

因为编译器会在预编译的时候用真身替换替身,而在我们的代码里面却又用常常用替身来帮忙。

看例子:#definePI3.141592654在此后的代码中你尽可以使用PI来代替3.141592654,而且你最好就这么做。

不然的话,如果我要把PI的精度再提高一些,你是否愿意一个一个的去修改这串数呢?你能保*不漏不出错?而使用PI的话,我们却只需要修改一次(这是十分高效的)。

这种情况还不是最要命的,我们再看一个例子:#defineERROR_POWEROFF-1如果你在代码里不用ERROR_POWEROFF这个宏而用-1,尤其在函数返回错误代码的时候(往往一个开发一个系统需要定义很多错误代码)。

肯怕上帝都无法知道-1表示的是什么意思吧。

这个-1,我们一般称为“魔鬼数”,上帝遇到它也会发狂的。

所以,我奉劝你代码里一定不要出现“魔鬼数”。

(这里是从代码可读*的角度进行考虑!) 但是我们利用define来定义数值类型的数据,一般只是用来定义常量,如果要定义一些变量,则可以使用c语言中const这个关键字。

我们已经讨论了const这个关键字,我们知道const修饰的数据是有类型的,而define宏定义的数据没有类型。

为了安全,我建议你以后在定义一些宏常数的时候用const代替,编译器会给const修饰的只读变量做类型校验,减少错误的可能。

define宏定义细节及uCOS中宏定义技巧

define宏定义细节及uCOS中宏定义技巧

define宏定义细节及uCOS中宏定义技巧1.预编译阶段把所有#include ”***.h“ (“”与<>的区别这⾥就不说了)⽤***.h的内容来替换了,所以之后就没有.h了,所有.h的内容都已经包含进了需要它们的.c中2.⽣成最后的exe⽂件是由编译、链接两步完成的,编译是源代码⽣成obj⼆进制⽬标⽂件的过程,注意⼀个源代码⽂件(指.c,⽽⾮.h,.h 已经被包含进.c中了)⽣成⼀个obj⽂件,由于编译是独⽴的,所以在两个独⽴的编译单元⾥是可以有重名的函数的,例如a.c中可以有⼀个void fun(); b.c中可同时有⼀个void fun(); 这点⼗分重要,⼤家可以试⼀下并且理解清楚3.编译期间,我们只要声明了的东西就能使⽤,⽽⽆需它的定义,声明可以重复,extern在编译时是告诉该编译单元该变量的定义在别的编译单元⾥,相当于声明,链接时,定义在整个程序中有且仅有⼀份,例如如下代码,编译可通过,但链接时失败。

4.#ifndef #define #endif 只在⼀个.c⽂件中有效,即在⼀个.c⽂件中define了⼀个宏,那么在另外⼀个.c中,这个宏是没有被define过的。

在下⾯的例⼦中,即使使⽤了宏,也会报错,因为在两个.c中都包含了.h,⽽.h中有两个定义(⽽不是声明),造成了linking时的重定义错误//main.c#include <a.h>int main(){}//a.h#ifndef A_H_#define A_H_void fun(void){};int x;#endif//ac.c#include <a.h>void test(){}Build之后发现如下linking错误5.#ifndef不能防⽌上述这种情况,那么应该⽤于哪⾥呢?有时候可能会在⼀个.c⽂件中包含了两次相同的.h⽂件,或者包含了两个不同的.h,但这两个.h⼜互相包含,这个时候#ifndef 就会起作⽤了6.为了彻底防⽌错误的出现,.h应该不产⽣代码,不⽤于定义,只⽤于宏定义、声明等7.在Keil的设置⾥⾯,预处理Define下⾯写的宏会在每个.c⽂件中都define过8.uCOS中的define技巧:在os_core.c中,有#ifndef OS_MASTER_FILE#define OS_GLOBALS#include <ucos_ii.h>#endif在其他的.c中,有#ifndef OS_MASTER_FILE#include <ucos_ii.h>#endif然后在ucos_ii.h中,有#ifdef OS_GLOBALS#define OS_EXT#else#define OS_EXT extern#endif我们可以看到,在os_core.c中,ucos_ii.h中带OS_EXT前缀的都变成了定义,⽽在其他.c中,带OS_EXT前缀的都是声明,这样就完成了⼀个.h即实现了定义,⼜实现了声明。

define宏定义

define宏定义

define宏定义在将一个C源程序转换为可执行程序的过程中, 编译预处理是最初的步骤. 这一步骤是由预处理器(preprocessor)来完成的. 在源流程序被编译器处理之前, 预处理器首先对源程序中的"宏(macro)"进行处理.C初学者可能对预处理器没什么概念, 这是情有可原的: 一般的C 编译器都将预处理, 汇编, 编译, 连接过程集成到一起了. 编译预处理往往在后台运行. 在有的C编译器中, 这些过程统统由一个单独的程序来完成, 编译的不同阶段实现这些不同的功能. 可以指定相应的命令选项来执行这些功能. 有的C编译器使用分别的程序来完成这些步骤. 可单独调用这些程序来完成. 在gcc中, 进行编译预处理的程序被称为CPP, 它的可执行文件名为cpp.编译预处理命令的语法与C语言的语法是完全独立的. 比如: 你可以将一个宏扩展为与C语法格格不入的内容, 但该内容与后面的语句结合在一个若能生成合法的C语句, 也是可以正确编译的.(一) 预处理命令简介预处理命令由#(hash字符)开头, 它独占一行, #之前只能是空白符. 以#开头的语句就是预处理命令, 不以#开头的语句为C中的代码行. 常用的预处理命令如下:#define定义一个预处理宏#undef 取消宏的定义#include 包含文件命令#include_next与#include相似, 但它有着特殊的用途#if编译预处理中的条件命令, 相当于C语法中的if 语句#ifdef判断某个宏是否被定义, 若已定义, 执行随后的语句#ifndef与#ifdef相反, 判断某个宏是否未被定义#elif若#if, #ifdef, #ifndef或前面的#elif条件不满足, 则执行#elif之后的语句, 相当于C语法中的else-if#else与#if, #ifdef, #ifndef对应, 若这些条件不满足, 则执行#else之后的语句, 相当于C语法中的else#endif #if, #ifdef, #ifndef这些条件命令的结束标志.defined 与#if, #elif配合使用, 判断某个宏是否被定义#line标志该语句所在的行号#将宏参数替代为以参数值为内容的字符窜常量##将两个相邻的标记(token)连接为一个单独的标记#pragma说明编译器信息#warning显示编译警告信息#error 显示编译错误信息(二) 预处理的文法预处理并不分析整个源代码文件, 它只是将源代码分割成一些标记(token), 识别语句中哪些是C语句, 哪些是预处理语句. 预处理器能够识别C标记, 文件名, 空白符, 文件结尾标志.预处理语句格式: #command name(...) token(s)1, command预处理命令的名称, 它之前以#开头, #之后紧随预处理命令, 标准C允许#两边可以有空白符, 但比较老的编译器可能不允许这样. 若某行中只包含#(以及空白符), 那么在标准C中该行被理解为空白. 整个预处理语句之后只能有空白符或者注释, 不能有其它内容.2, name代表宏名称, 它可带参数. 参数可以是可变参数列表(C99).3, 语句中可以利用"\"来换行.e.g.# define ONE 1 /* ONE == 1 */等价于: #define ONE 1#define err(flag, msg) if(flag) \printf(msg)等价于: #define err(flag, msg) if(flag) printf(msg)(三) 预处理命令详述1, #define#define命令定义一个宏:#define MACRO_NAME(args) tokens(opt)之后出现的MACRO_NAME将被替代为所定义的标记(tokens). 宏可带参数, 而后面的标记也是可选的.对象宏不带参数的宏被称为"对象宏(objectlike macro)"#define经常用来定义常量, 此时的宏名称一般为大写的字符串. 这样利于修改这些常量.e.g.#define MAX 100int a[MAX];#ifndef __FILE_H__#define __FILE_H__#include "file.h"#endif#define __FILE_H__ 中的宏就不带任何参数, 也不扩展为任何标记. 这经常用于包含头文件.要调用该宏, 只需在代码中指定宏名称, 该宏将被替代为它被定义的内容.函数宏带参数的宏也被称为"函数宏". 利用宏可以提高代码的运行效率: 子程序的调用需要压栈出栈, 这一过程如果过于频繁会耗费掉大量的CPU运算资源. 所以一些代码量小但运行频繁的代码如果采用带参数宏来实现会提高代码的运行效率.函数宏的参数是固定的情况函数宏的定义采用这样的方式: #define name( args ) tokens其中的args和tokens都是可选的. 它和对象宏定义上的区别在于宏名称之后不带括号.注意, name之后的左括号(必须紧跟name, 之间不能有空格, 否则这就定义了一个对象宏, 它将被替换为以(开始的字符串. 但在调用函数宏时, name与(之间可以有空格.e.g.#define mul(x,y) ((x)*(y))注意, 函数宏之后的参数要用括号括起来, 看看这个例子:e.g.#define mul(x,y) x*y"mul(1, 2+2);" 将被扩展为: 1*2 + 2同样, 整个标记串也应该用括号引用起来:e.g.#define mul(x,y) (x)*(y)sizeof mul(1,2.0) 将被扩展为 sizeof 1 * 2.0调用函数宏时候, 传递给它的参数可以是函数的返回值, 也可以是任何有意义的语句:e.g.mul (f(a,b), g(c,d));e.g.#define insert(stmt) stmtinsert ( a=1; b=2;) 相当于在代码中加入 a=1; b=2 .insert ( a=1, b=2;) 就有问题了: 预处理器会提示出错: 函数宏的参数个数不匹配. 预处理器把","视为参数间的分隔符.insert ((a=1, b=2;)) 可解决上述问题.在定义和调用函数宏时候, 要注意一些问题:1, 我们经常用{}来引用函数宏被定义的内容, 这就要注意调用这个函数宏时的";"问题.example_3.7:#define swap(x,y) { unsigned long _temp=x; x=y; y=_tmp}如果这样调用它: "swap(1,2);" 将被扩展为: { unsigned long _temp=1; 1=2; 2=_tmp};明显后面的;是多余的, 我们应该这样调用: swap(1,2)虽然这样的调用是正确的, 但它和C语法相悖, 可采用下面的方法来处理被{}括起来的内容:#define swap(x,y) \do { unsigned long _temp=x; x=y; y=_tmp} while (0)swap(1,2); 将被替换为:do { unsigned long _temp=1; 1=2; 2=_tmp} while (0);在Linux内核源代码中对这种do-while(0)语句有这广泛的应用.2, 有的函数宏是无法用do-while(0)来实现的, 所以在调用时不能带上";", 最好在调用后添加注释说明.eg_3.8:#define incr(v, low, high) \for ((v) = (low),; (v) <= (high); (v)++)只能以这样的形式被调用: incr(a, 1, 10) /* increase a form 1 to 10 */函数宏中的参数包括可变参数列表的情况C99标准中新增了可变参数列表的内容. 不光是函数, 函数宏中也可以使用可变参数列表.#define name(args, ...) tokens#define name(...) tokens"..."代表可变参数列表, 如果它不是仅有的参数, 那么它只能出现在参数列表的最后. 调用这样的函数宏时, 传递给它的参数个数要不少于参数列表中参数的个数(多余的参数被丢弃).通过__VA_ARGS__来替换函数宏中的可变参数列表. 注意__VA_ARGS__只能用于函数宏中参数中包含有"..."的情况.e.g.#ifdef DEBUG#define my_printf(...) fprintf(stderr, __VA_ARGS__)#else#define my_printf(...) printf(__VA_ARGS__)#endiftokens中的__VA_ARGS__被替换为函数宏定义中的"..."可变参数列表.注意在使用#define时候的一些常见错误:#define MAX = 100#define MAX 100;=, ; 的使用要值得注意. 再就是调用函数宏是要注意, 不要多给出";".关于定义宏的另外一些问题(1) 宏可以被多次定义, 前提是这些定义必须是相同的. 这里的"相同"要求先后定义中空白符出现的位置相同, 但具体的空白符类型或数量可不同, 比如原先的空格可替换为多个其他类型的空白符: 可为tab, 注释...e.g.#define NULL 0#define NULL /* null pointer */ 0上面的重定义是相同的, 但下面的重定义不同:#define fun(x) x+1#define fun(x) x + 1 或: #define fun(y) y+1如果多次定义时, 再次定义的宏内容是不同的, gcc会给出"NAME redefined"警告信息.应该避免重新定义函数宏, 不管是在预处理命令中还是C语句中, 最好对某个对象只有单一的定义. 在gcc中, 若宏出现了重定义, gcc会给出警告.(2) 在gcc中, 可在命令行中指定对象宏的定义:e.g.$ gcc -Wall -DMAX=100 -o tmp tmp.c相当于在tmp.c中添加" #define MAX 100".那么, 如果原先tmp.c中含有MAX宏的定义, 那么再在gcc调用命令中使用-DMAX, 会出现什么情况呢?---若-DMAX=1, 则正确编译.---若-DMAX的值被指定为不为1的值, 那么gcc会给出MAX宏被重定义的警告, MAX的值仍为1.注意: 若在调用gcc的命令行中不显示地给出对象宏的值, 那么gcc 赋予该宏默认值(1), 如: -DVAL == -DVAL=1(3) #define所定义的宏的作用域宏在定义之后才生效, 若宏定义被#undef取消, 则#undef之后该宏无效. 并且字符串中的宏不会被识别e.g.#define ONE 1sum = ONE + TWO /* sum = 1 + TWO */#define TWO 2sum = ONE + TWO /* sum = 1 + 2 */#undef ONEsum = ONE + TWO /* sum = ONE + 2 */char c[] = "TWO" /* c[] = "TWO", NOT "2"! */(4) 宏的替换可以是递归的, 所以可以嵌套定义宏.e.g.# define ONE NUMBER_1# define NUMBER_1 1int a = ONE /* a = 1 */2, #undef#undef用来取消宏定义, 它与#define对立:#undef name如够被取消的宏实际上没有被#define所定义, 针对它的#undef 并不会产生错误.当一个宏定义被取消后, 可以再度定义它.3, #if, #elif, #else, #endif#if, #elif, #else, #endif用于条件编译:#if 常量表达式1语句...#elif 常量表达式2语句...#elif 常量表达式3语句......#else语句...#endif#if和#else分别相当于C语句中的if, else. 它们根据常量表达式的值来判别是否执行后面的语句. #elif相当于C中的else-if. 使用这些条件编译命令可以方便地实现对源代码内容的控制.else之后不带常量表达式, 但若包含了常量表达式, gcc只是给出警告信息.使用它们可以提升代码的可移植性---针对不同的平台使用执行不同的语句. 也经常用于大段代码注释.e.g.#if 0{一大段代码;}#endif常量表达式可以是包含宏, 算术运算, 逻辑运算等等的合法C常量表达式, 如果常量表达式为一个未定义的宏, 那么它的值被视为0.#if MACRO_NON_DEFINED == #if 0在判断某个宏是否被定义时, 应当避免使用#if, 因为该宏的值可能就是被定义为0. 而应当使用下面介绍的#ifdef或#ifndef.注意: #if, #elif, #else之后的宏只能是对象宏. 如果name为名的宏未定义, 或者该宏是函数宏. 那么在gcc中使用"-Wundef"选项会显示宏未定义的警告信息.4, #ifdef, #ifndef, defined.#ifdef, #ifndef, defined用来测试某个宏是否被定义#ifdef name 或 #ifndef name它们经常用于避免头文件的重复引用:#ifndef __FILE_H__#define __FILE_H__#include "file.h"#endifdefined(name): 若宏被定义,则返回1, 否则返回0.它与#if, #elif, #else结合使用来判断宏是否被定义, 乍一看好像它显得多余, 因为已经有了#ifdef和#ifndef. defined用于在一条判断语句中声明多个判别条件:#if defined(VAX) && defined(UNIX) && !defined(DEBUG)和#if, #elif, #else不同, #indef, #ifndef, defined测试的宏可以是对象宏, 也可以是函数宏. 在gcc中使用"-Wundef"选项不会显示宏未定义的警告信息.5, #include , #include_next#include用于文件包含. 在#include 命令所在的行不能含有除注释和空白符之外的其他任何内容.#include "headfile"#include <headfile>#include 预处理标记前面两种形式大家都很熟悉, "#include 预处理标记"中, 预处理标记会被预处理器进行替换, 替换的结果必须符合前两种形式中的某一种.实际上, 真正被添加的头文件并不一定就是#include中所指定的文件. #include"headfile"包含的头文件当然是同一个文件, 但#include <headfile>包包含的"系统头文件"可能是另外的文件. 但这不值得被注意. 感兴趣的话可以查看宏扩展后到底引入了哪些系统头文件.关于#include "headfile"和#include <headfile>的区别以及如何在gcc中包含头文件的详细信息, 参考本blog的GCC笔记.相对于#include, 我们对#include_next不太熟悉. #include_next 仅用于特殊的场合. 它被用于头文件中(#include既可用于头文件中, 又可用于.c文件中)来包含其他的头文件. 而且包含头文件的路径比较特殊: 从当前头文件所在目录之后的目录来搜索头文件.比如: 头文件的搜索路径一次为A,B,C,D,E. #include_next所在的当前头文件位于B目录, 那么#include_next使得预处理器从C,D,E目录来搜索#include_next所指定的头文件.可参考cpp手册进一步了解#include_next6, 预定义宏标准C中定义了一些对象宏, 这些宏的名称以"__"开头和结尾, 并且都是大写字符. 这些预定义宏可以被#undef, 也可以被重定义.下面列出一些标准C中常见的预定义对象宏(其中也包含gcc自己定义的一些预定义宏:__LINE__ 当前语句所在的行号, 以10进制整数标注.__FILE__ 当前源文件的文件名, 以字符串常量标注.__DATE__ 程序被编译的日期, 以"Mmm dd yyyy"格式的字符串标注.__TIME__ 程序被编译的时间, 以"hh:mm:ss"格式的字符串标注, 该时间由asctime返回.__STDC__如果当前编译器符合ISO标准, 那么该宏的值为1__STDC_VERSION__如果当前编译器符合C89, 那么它被定义为199409L, 如果符合C99, 那么被定义为199901L.我用gcc, 如果不指定-std=c99, 其他情况都给出__STDC_VERSION__未定义的错误信息, 咋回事呢?__STDC_HOSTED__ 如果当前系统是"本地系统(hosted)", 那么它被定义为1. 本地系统表示当前系统拥有完整的标准C库.gcc定义的预定义宏:__OPTMIZE__ 如果编译过程中使用了优化, 那么该宏被定义为1.__OPTMIZE_SIZE__同上, 但仅在优化是针对代码大小而非速度时才被定义为1.__VERSION__ 显示所用gcc的版本号.可参考"GCC the complete reference".要想看到gcc所定义的所有预定义宏, 可以运行: $ cpp -dM /dev/null7, #line#line用来修改__LINE__和__FILE__.e.g.printf("line: %d, file: %s\n", __LINE__, __FILE__);#line 100 "haha"printf("line: %d, file: %s\n", __LINE__, __FILE__);printf("line: %d, file: %s\n", __LINE__, __FILE__);显示:line: 34, file: 1.cline: 100, file: hahaline: 101, file: haha8, #pragma, _Pragma#pragma用编译器用来添加新的预处理功能或者显示一些编译信息. #pragma的格式是各编译器特定的, gcc的如下:#pragma GCC name token(s)#pragma之后有两个部分: GCC和特定的pragma name. 下面分别介绍gcc中常用的.(1) #pragma GCC dependencydependency测试当前文件(既该语句所在的程序代码)与指定文件(既#pragma语句最后列出的文件)的时间戳. 如果指定文件比当前文件新, 则给出警告信息.e.g.在demo.c中给出这样一句:#pragma GCC dependency "temp-file"然后在demo.c所在的目录新建一个更新的文件: $ touch temp-file, 编译: $ gcc demo.c会给出这样的警告信息: warning: current file is older than temp-file如果当前文件比指定的文件新, 则不给出任何警告信息.还可以在在#pragma中给添加自定义的警告信息.e.g.#pragma GCC dependency "temp-file" "demo.c needs to be updated!"1.c:27:38: warning: extra tokens at end of #pragma directive1.c:27:38: warning: current file is older than temp-file注意: 后面新增的警告信息要用""引用起来, 否则gcc将给出警告信息.(2) #pragma GCC poison token(s)若源代码中出现了#pragma中给出的token(s), 则编译时显示警告信息. 它一般用于在调用你不想使用的函数时候给出出错信息.e.g.#pragma GCC poison scanfscanf("%d", &a);warning: extra tokens at end of #pragma directiveerror: attempt to use poisoned "scanf"注意, 如果调用了poison中给出的标记, 那么编译器会给出的是出错信息. 关于第一条警告, 我还不知道怎么避免, 用""将token(s)引用起来也不行.(3) #pragma GCC system_header从#pragma GCC system_header直到文件结束之间的代码会被编译器视为系统头文件之中的代码. 系统头文件中的代码往往不能完全遵循C标准, 所以头文件之中的警告信息往往不显示. (除非用#warning显式指明).(这条#pragma语句还没发现用什么大的用处)由于#pragma不能用于宏扩展, 所以gcc还提供了_Pragma:e.g.#define PRAGMA_DEP #pragma GCC dependency "temp-file"由于预处理之进行一次宏扩展, 采用上面的方法会在编译时引发错误, 要将#pragma语句定义成一个宏扩展, 应该使用下面的_Pragma语句:#define PRAGMA_DEP _Pragma("GCC dependency \"temp-file\"")注意, ()中包含的""引用之前引该加上\转义字符.9, #, ###和##用于对字符串的预处理操作, 所以他们也经常用于printf, puts之类的字符串显示函数中.#用于在宏扩展之后将tokens转换为以tokens为内容的字符串常量.e.g.#define TEST(a,b) printf( #a "<" #b "=%d\n", (a)<(b));注意: #只针对紧随其后的token有效!##用于将它前后的两个token组合在一起转换成以这两个token 为内容的字符串常量. 注意##前后必须要有token.e.g.#define TYPE(type, n) type n之后调用:TYPE(int, a) = 1;TYPE(long, b) = 1999;将被替换为:int a = 1;long b = 1999;(10) #warning, #error#warning, #error分别用于在编译时显示警告和错误信息, 格式如下:#warning tokens#error tokense.g.#warning "some warning"注意, #error和#warning后的token要用""引用起来!(在gcc中, 如果给出了warning, 编译继续进行, 但若给出了error, 则编译停止. 若在命令行中指定了 -Werror, 即使只有警告信息, 也不编译.。

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

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.当用##连接形参时,##前后的空格可有可无。

如:#define exampleNum(n) num ## n 相当于#define exampleNum(n) num##n2.连接后的实际参数名,必须为实际存在的参数名或是编译器已知的宏定义// preprocessor_token_pasting.cpp#include <stdio.h>#define paster( n ) printf_s( "token" #n " = %d", token##n )int token9 = 9;int main(){paster(9);}运行结果:token9 = 93、@# (charizing)字符化操作符。

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

作用是将传的单字符参数名转换成字符,以一对单引用括起来。

#define makechar(x) #@xa = makechar(b);展开后变成了:a= 'b';4、\ 行继续操作符当定义的宏不能用一行表达完整时,可以用"\"表示下一行继续此宏的定义。

注意:换行不能切断单词,只能在空格的地方进行。

在#define中,标准只定义了#和##两种操作。

#用来把参数转换成字符串,##则用来连接两个前后两个参数,把它们变成一个字符串。

#include <stdio.h>#define paster( n ) printf( "token " #n" = %d\n ", token##n )int main(){int token9=10;paster(9);return 0;}输出为[leshy@leshy src]$ ./a.outtoken 9 = 10宏定义的特殊符号# ## - [C++]1. 利用宏参数创建字符串:# 运算符在类函数宏(function-like macro)的替换部分中,“#”符号用作一个预处理运算符,它可以把语言符号(token)转化为字符串。

例如,如果x 是一个宏参量,那么#x 可以把参数名转化为相应的字符串。

该过程称为字符串化。

说明:类函数宏就是带参数的宏。

类函数宏的定义中,用圆括号括起来一个或多个参数,随后这些参数出现在替换部分。

#include <stdio.h>#define PSQR(x) printf("The square of " #x " is %d. \r\n", (x) * (x))int main(void){int y = 5;PSQR(y);PSQR(2 + 4);return 0;}// 输出:The square of y is 25. // 用"y" 代替#xThe square of 2 + 4 is 36. // 用"2 + 4" 代替#x#include <stdio.h>#define PSQR(x) printf("The square of " #x " is %d. \r\n", (x) * (x))int main(void){int y = 5;PSQR(y);PSQR(2 + 4);return 0;}// 输出:The square of y is 25. // 用"y" 代替#xThe square of 2 + 4 is 36. // 用"2 + 4" 代替#x#define STRING2(x) #x#define STRING(x) STRING2(x)#define WQ wangqi#pragma message(STRING2(WQ)) // WQ(字符串)#pragma message(STRING(WQ)) // wangqi(字符串)#define STRING2(x) #x#define STRING(x) STRING2(x)#define WQ wangqi#pragma message(STRING2(WQ)) // WQ(字符串)#pragma message(STRING(WQ)) // wangqi(字符串)2. 预处理器的粘合剂:## 运算符和# 运算符一样,## 运算符可以用于类函数宏的替换部分。

另外,## 运算符还可用于类对象宏(object-like macro)的替换部分。

这个运算符把两个语言符号组合成单个语言符号。

例如,可以定义如下宏:#define XNAME(n) x ## n#define XNAME(n) x ## n宏调用XNAME(4) 会展开成x4 。

说明:类对象宏就是用来代表值的宏。

如,#define PI 3.141593 中的PI。

#include <stdio.h>#define XNAME(n) x ## n#define PRINT_XN(n) printf("x" #n " = %d\r\n", x ## n);int main(void){int XNAME(1) = 14; // 变为int x1 = 14;int XNAME(2) = 20; // 变为int x2 = 20;PRINT_XN(1) // 变为printf("x1 = %d\r\n", x1);PRINT_XN(2) // 变为printf("x2 = %d\r\n", x2);return 0;}// 输出:x1 = 14x2 = 20#include <stdio.h>#define XNAME(n) x ## n#define PRINT_XN(n) printf("x" #n " = %d\r\n", x ## n);int main(void){int XNAME(1) = 14; // 变为int x1 = 14;int XNAME(2) = 20; // 变为int x2 = 20;PRINT_XN(1) // 变为printf("x1 = %d\r\n", x1);PRINT_XN(2) // 变为printf("x2 = %d\r\n", x2);return 0;}// 输出:x1 = 14x2 = 20#define __T(x) L ## x#define _T(x) __T(x)#define _TEXT(x) __T(x)#define WQ "wangqi"#pragma message(__T(WQ)) // LWQ (标识符)wcout << _T(WQ); // wangqi(宽字节字符串)#define __T(x) L ## x#define _T(x) __T(x)#define _TEXT(x) __T(x)#define WQ "wangqi"#pragma message(__T(WQ)) // LWQ (标识符)wcout << _T(WQ); // wangqi(宽字节字符串)3. 语言符号从技术方面看,系统把宏的主体当作语言符号(token)类型字符串,而不是字符型字符串。

C 预处理器中的语言符号是宏定义主体中的单独的“词(word)”。

用空白字符把这些词分开。

例如:#define FOUR 2*2#define FOUR 2*2这个定义中有一个语言符号:即序列2*2 。

但是:#define SIX 2 * 3#define SIX 2 * 3这个定义中有三个语言符号:2、* 和3 。

在处理主体中的多个空格时,字符型字符串和语言符号型字符串采用不同方法。

考虑下面的定义:#define EIGHT 4 * 8#define EIGHT 4 * 8把主体解释为字符型字符串时,预处理器用4 * 8 替换EIGHT 。

也就是说,额外的空格也当作替换文本的一部分。

但是,当把主体解释为语言符号类型时,预处理器用由单个空格分隔的三个语言符号,即4 * 8 来替换EIGHT 。

换句话说,用字符型字符串的观点看,空格也是主体的一部分;而用语言符号字符串的观点看,空格只是分隔主体中语言符号的符号。

在实际应用中,有些C 编译器把宏主体当作字符串而非语言符号。

相关文档
最新文档