#define MAX 100;//在定义标识符的时候加上了一个分号,在正常的语句下,连续使用两个分号,编译器会认为后面那个是一个空语句,但是在下面的场景会出现问题: if(condition)...max = MAX; else max = 0; if语句不加中括号,默认只会跟着一条语句,这里相当于是有两条语句了,下面再出现else的时候就会出现语法错误。...所以宏比函数在程序的规模和速度方面更胜一筹。 宏与类型无关。 当然,宏相比函数也有缺点 每次使用宏的时候,一份宏定义的代码插入到程序中。除非宏比较短,否则可能会大幅度增加程序的长度。...3、宏参数的替换是不经过计算的,有可能会带有副作用,所以我们在写宏体的时候一般在能加括号的地方都不要吝啬括号,但有时候这也不能解决副作用的问题。函数在传参时传的是值,不会产生副作用。...6、函数在调用时会产生时间和空间上的开销;宏在调用时则没有,因为宏进行的只是简单的字符串替换。 7、如果使用宏比较多,宏体在展开时会产生大量的代码,大大降低运行时间。
一种常见的错误是在宏定义中使用 = : #define N = 100 /*** WRONG ***/ int a[N]; /* 会成为 int a[= 100]; */ 在上面的例子中,我们(错误地)...在一个宏定义中,编译器可以检测到绝大多数由多余符号所导致的错误。但不幸的是,编译器会将每一处使用这个宏的地方标为错误,而不会直接找到错误的根源——宏定义本身,因为宏定义已经被预处理器删除了。...当宏作为常量使用时,C程序员习惯在名字中只使用大写字母。但是并没有如何将用于其他目的的宏大写的统一做法。由于宏(特别是带参数的宏)可能是程序中错误的来源,所以一些程序员更喜欢使用大写字母来引起注意。...这些参数可以在替换列表中根据需要出现任意次。 在宏的名字和左括号之间必须没有空格。如果有空格,预处理器会认为是在定义一个简单的宏,其中(x1,x2,…,xn)是替换列表的一部分。...(i+1*10); 由于乘法的优先级比加法高,这条语句等价于 j = i+10; 当然,我们希望的是 j = (i+1)*10; 在宏定义中缺少圆括号会导致C语言中最让人讨厌的错误
一、#define的基本语法 在C语言中,常量是使用频率很高的一个量。常量是指在程序运行过程中,其值不能被改变的量。常量常使用#define来定义。...这里会出现语法错误。 四、#define定义宏 #define 机制包括了一个规定,允许把参数替换到文本中,这种实现通常称为宏(macro)或定义宏(define macro)。...在宏定义上加上两个括号,这个问题便轻松的解决了: #define SQUARE(x) (x) * (x) 这样预处理之后就产生了预期的效果: printf ("%d\n",(a + 1) * (...a + 1) ); 这里还有一个宏定义: #define DOUBLE(x) (x) + (x) 定义中我们使用了括号,想避免之前的问题,但是这个宏可能会出现新的错误。...#define DOUBLE( x) ( ( x ) + ( x ) ) 提示: 所以用于对数值表达式进行求值的宏定义都应该用这种方式加上括号,避免在使用宏时由于参数中的操作符或邻近操作符之间不可预料的相互作用
当需要获取当前文件的路径和文件名时,可以使用这个常量。 在进行编译的源文件中,使用 FILE 会返回当前源文件的路径和文件名。...在宏定义上加上两个括号,这个问题便轻松的解决了 #define SQUARE(x) (x) * (x) 这样预处理之后就产生了预期的效果: printf ("%d\n",(a + 1) * (a + 1...) ); 这里还有一个宏定义: #define DOUBLE(x) (x) + (x) 定义中我们使用了括号,想避免之前的问题,但是这个宏可能会出现新的错误。...#define DOUBLE( x) ( ( x ) + ( x ) ) 提示: 所以用于对数值表达式进行求值的宏定义都应该用这种方式加上括号,避免在使用宏时由于参数中的操作符或邻近操作符之间不可预料的相互作用...,除非加上括号,否则临近操作符的优先级可能会产生不可预料的后果,所以建议宏在书写的时候多些括号。
*(1)) 宏定义不必带有括号,通过在宏主体中编写不平衡的开放括号,可以创建一个从宏主体内部开始但在宏主体外部结束的宏调用。...s %d", p, 35) 组合宏调用的功能可能会很有用,但是在宏主体中使用不平衡的开放括号只会造成混淆,应该避免。...运算符优先级问题 在大多数宏定义示例中,每次出现的宏参数名称都带有括号,并且另一对括号通常会包围整个宏定义,这是编写宏最好的方式。...x_ : y_; }) “({{…})”符号产生一个复合表达式,它的值是其最后一条语句的值。 如果不使用GNU C扩展,唯一的解决方案是在使用宏min时要小心。...在这种情况下,该问题可以通过使用相同的括号轻松解决,该括号应用于防止算术运算的错误嵌套: #define foo (a,b) or #define bar(x) lose((x)) 多余的一对括号可防止
#endif 一般都用在条件判断语句内容中,后面都跟着双引号带着的消息,error指令会直接中止编译,抛出错误消息,warning也会抛出警告消息,但不会中止编译。...发生错误后,会抛出说"文件名"文件的第11行有错误。后面跟着的文件名是一个可选项,写了就可以在消息中显示,不写也没关系。...定义函数宏的时候,有一个细节要注意,就是要多对参数使用括号: #defind SQUARE(x) ((x) * (x)) 为什么要这么麻烦?为什么不能直接 x * x?...,所以都应该使用括号。...此外,如果你的代码有多行,还应该使用大括号括起来: #define FUNC(a, b) {a = a + b; b = a - b;} 此外,不要过度使用宏!
在宏定义上加上两个括号,这个问题便轻松的解决了: #define SQUARE(x) (x) * (x) 这样预处理之后就产生了预期的效果: printf("%d\n",(a + 1) * (a + 1...) ); 这里还有一个宏定义: #define DOUBLE(x) (x)+(x) 定义中我们使用了括号,想避免之前的问题,但是这个宏可能会出现新的错误。...#define DOUBLE(x) ( (x) + (x) ) 即所有用于对数值表达式进行求值的宏定义都应该用这种方式加上括号,避免在使用宏时由于参数中的操作符或邻近操作符之间不可预料的相互作用。...,否则邻近操作符的优先级可能会产生不可预料的后果,所以建议在书写的时候多些括号。...函数参数只在函数调用的时候求值一次,它的结果值传递给函数,表达式的求值结果更容易预测。 带有副作用的参数 参数可能被替换到宏体的多个位置,所以带有副作用的参数求值可能会产生不可预料的后果。
这个时候程序将使用一个运行时堆栈(stack),存储函数的局部变量和返回地址。程序同时也可以使用静态(static)内存,存储于静态内存中的变量在程序的整个执行过程一直保留他们的值。 终止程序。...错误,由替换产生的表达式并没有按照预想的次序进行求值 //a = 5+1*5+1 = 11 //在宏定义上加上两个括号,这个问题便轻松的解决了: return 0; } #define...所以用于对数值表达式进行求值的宏定义都应该用这种方式加上括号,避免在使用宏时由于参数中的操作符或邻近操作符之间不可预料的相互作用 #define 替换规则 在程序中扩展#define定义符号和宏时,需要涉及几个步骤...符 优 先 级 宏参数的求值是在所有周围表达式的上下文环境里, 除非加上括号,否则邻近操作符的优先级可能会产生 不可预料的后果,所以建议宏在书写的时候多些括 号。...带 有 副 作 用 的 参 数 参数可能被替换到宏体中的多个位置,所以带有副作 用的参数求值可能会产生不可预料的结果。 函数参数只在传参的时候求值一 次,结果更容易控制。
如何解决,那也很简单: 在宏定义上加上两个括号,这个问题便轻松的解决了: #define SQUARE(x) (x) * (x) 这样预处理之后就产生了预期的效果: printf ("%d\n"...#define DOUBLE( x ) ((x) + (x)) 所以我们得出结论: 用于对数值表达式进行求值的宏定义都应该用这种方式加上括号,避免在使用宏时由于参数中的操作符或邻近操作符之间不可预料的相互作用...所以: 尽量不要使用带有副作用的宏参数,以避免产生一些不可预料的结果。 5....这个其实我们在讲宏的时候就演示过了,在使用宏的时候,有些地方如果我们不加括号,可能就会导致由替换产生的表达式因为操作符优先级的问题而并没有按照我们预想的次序进行求值。...如果还找不到就提示编译错误。 10.1.2 库文件包含 #include 对于C标准库里的头文件,我们使用尖括号来包含。
为了避免类似的错误,定义宏时,参数应该加上括号,宏本身也应该加上括号。...宏可能会带来运算符优先级的问题,导致程序出现错误。 ** 属性** #define定义宏 函数 代码长度 每次使用宏时,宏代码都会插入程序中。...除了非常小的宏外,程序的长度会大幅增长 函数代码只出现在一个地方,每次使用这个函数时,都调用那个地方的同一份代码 执行速度 更快 存在函数的调用和返回的额外开销,相对慢一些 操作符优先级 宏参数的求值是在所有周围的上下文环境中...,除非加上括号,否则邻近操作符的优先级可能会产生不可预料的后果,所以在宏的书写时尽量多加些括号 函数参数只在函数调用的时候求值一次,他的结果值传递给函数。...表达式的求值结果更容易预测 带有副作用的参数 参数可能被替换到宏体中的多个位置,所以带有副作用的参数求值可能会产生不可预测的结果 函数参数只在传参的时候求值一次,结果更容易控制 参数类型 宏的参数与类型无关
1 概述 在工程规模较小,不是很复杂,与硬件结合紧密,要求移植性的时候,可采用宏定义简化编程,增强程序可读性。 当宏作为常量使用时,C程序员习惯在名字中只使用大写字母。...由于宏(特别是带参数的宏)可能是程序中错误的来源,所以一些程序员更喜欢使用大写字母来引起注意。...";" 使用#define来为常量命名一些优点: 程序会更易读。...宏名采用大写字符组成的单词或其缩写序列,并在各单词之间使用“_”分隔。 如果需要公布某个宏,那么该宏定义应当放置在头文件中,否则放置在实现文件(.cpp)的顶部。...不要使用宏来定义新类型名,应该使用typedef,否则容易造成错误。 给宏添加注释时请使用块注释(/* */),而不要使用行注释。因为有些编译器可能会把宏后面的行注释理解为宏体的一部分。
带参宏在我们的嵌入式编程中使用得非常多,其定义如下: define 标识符(参数列表) 字符序列 其中参数列表中的参数之间用逗号分隔,字符序列中应包含参数表中的参数。...在定义带参数的宏时,宏名标识符与左圆括号之间不允许有空白符,应紧接在一起,否则变成了无参数的宏定义。 并且,字符序列与其每一个参数必须用括号扩起来,否则该宏定义可能会产生二义性 。...这就是因为我们不给字符序列中的宏参数加括号的原因,产生了歧义。程序生成可执行程序之前的预处理过程中把SQUARE(x+2)替换成了x+2*x+2,因此当x=5时res的结果为17。...和使用函数相比,使用宏的不利之处在于每次使用宏时,一份宏定义代码的拷贝都会插入到程序中。除非宏非常短,否则使用宏会大幅度增加程序的长度。 还有一些任务根本无法用函数实现,但是用宏定义却很好实现。...宏的缺点 宏可能会大幅度增加程序的长度。 宏是没法调试的。 宏由于与类型无关,也就不够严谨。 宏可能会带来运算符的优先级问题,即二义性。 以上就是关于带参宏的一些总结,如有错误,欢迎指出!
\n") 字符串常量化运算符(#) 在宏定义中,当需要把一个宏的参数转换为字符串常量时,则使用字符串常量化运算符(#)。在宏中使用的该运算符有一个特定的参数或参数列表。...这是怎么发生的,因为这个实例会从编译器产生下列的实际输出: printf ("token34 = %d", token34); 这个实例演示了 token##n 会连接到 token34 中,在这里,我们使用了字符串常量化运算符...(x)) 在使用带有参数的宏之前,必须使用 #define 指令定义。...参数列表是括在圆括号内,且必须紧跟在宏名称的后边。宏名称和左圆括号之间不允许有空格。例如: #include #define MAX(x,y) ((x) > (y) ?...: Max between 20 and 10 is 20 使用#define含参时,参数括号很重要,如上例中省略括号会导致运算错误: #include #define square
使用举例: 1、利用#define定义宏求一个数的平方 #define SQUARE( x ) x * x 这个宏接收⼀个参数 x .如果在上述声明之后,你把 SQUARE( 5 ); 置于程序中,预处理器就会...吸取上次的经验,我们给宏定义的参数加上括号,因此我们会这样写 #define DOUBLE(x) (x) + (x) 这时又出现了问题,第62行代码按道理应该输出100,但是却输出了55。...再外部再加一个大括号,来保证宏定义的加法在乘法运算之前!...2、⽤于对数值表达式进⾏求值的宏定义都应该⽤这种⽅式加上括号,避免在使⽤宏时由于参数中的 操作符或邻近操作符之间不可预料的相互作⽤。...五、宏替换的规则 在程序中扩展#define定义符号和宏时,需要涉及⼏个步骤。 1. 在调⽤宏时,首先先对参数进行检查,看看是否包含任何由#define定义的符号。如果是,它们⾸先被替换。 2.
3.2.3#define替换规则 在程序中扩展#define定义符号和宏时, 需要涉及这几个步骤: 1.在调用宏时,首先对参数进行检查,看看是否包含任何由#define定义的符号,如果是,他们首先被替换...4.宏有时候会带来运算符优先级问题,导致程序发生错误。 所以根据不同的情况进行选择使用宏还是函数有各自的优势。...宏和函数的对比: 属 性 #define定义宏 函数 代 码 长 度 每次使用时,宏代码都会被插入到程序中。..., 除非加上括号,否则邻近操作符的优先级可能会产生 不可预料的后果,所以建议宏在书写的时候多些括...用的参数求值可能会产生不可预料的结果。
否则替换的时候会将 ; 也替换过去,会导致语法错误 1.2.2 #define 定义宏 #define 机制包括了一个规定,允许把参数替换到文本中,这种实现通常会被解释为宏(macro)或定义宏(...中 注意: 参数列表的左括号必须与name紧邻 如果两者之间有任何空白存在,参数列表就会被释解释为stuff的一部分 如: #define定义宏也是完全替换,比如: 为了防止出现失误,我们在声明的时候需要加上括号...: 我们在写宏的时候,如果逻辑需要,我们可以加上足够多的括号来使宏变得完整 1.2.3 #define 替换规则 在程序中扩展#define定义符号和宏时,需要涉及几个步骤 在调用宏时,首先对参数进行检查...注意:这样的连接必须产生一个合法的标识符,否则其结果就是未定义的 1.2.5 带有副作用的宏参数 当宏参数在宏的定义中出现超过一次的时候,如果参数带有副作用,那么在使用这个宏的时候就可能出现危险,...宏可能会带来运算符优先级的问题,导致过程容易出现错误 宏有时候可以做函数做不到的事情,比如:宏的参数可以出现类型,但是函数做不到 对比 建议: 如果逻辑比较简单,可以使用宏来实现 如果计算逻辑比较负责
三、从一个简单的函数式宏说起 再来看下上面我们编写的计算面积的宏,正常情况下好像没什么问题,但是需要注意,归根结底宏并不是函数,如果完全把其作为函数使用,我们就可能会陷入一系列的陷阱中,比如这样使用...: CGFloat res = 3.1415926 * 1 + 1 * 1 + 1; 一目了然了,由于运算符的优先级问题导致了运算顺序错误,在编程中,所有运算符优先级产生的问题都可以使用一种方式解决:用小括号...,将参数替换了两次,由于参数本身是一个自加表达式,所以被自加了两次,产生了问题,那么这个问题怎么解决呢,C语言中有一种很有用的语法,即使用大括号定义代码块,代码块会将最后一条语句的执行结果返回,修改上面宏定义如下...如果你一下子不能理解为什么这样就可以解决宏展开的问题,你只需要记住这样一条宏展开的原则:如果形参有使用#或##这种处理符号,则不会进行宏参数的展开,否则先展开宏参数,在展开当前宏。...多语句功能性宏,要使用do-while包裹 这条原则看上去有些莫名其妙,但是其非常重要,例如,我们需要编写一个自定义的LOG宏,在进行打印时添加一些自定义的信息,你或许会这样写: #define
预处理指令简介 •C语言在对源程序进行编译之前,会先对一些特殊的预处理指令作解释(比如之前使用的#include文件包含指令),产生一个新的源程序(这个过程称为编译预处理),之后再进行通常的编译 •为了区分预处理指令和一般的...1> 宏名一般用大写字母,以便与变量名区别开来,但用小写也没有语法错误 • 2> 对程序中用双引号扩起来的字符串内的字符,不进行宏的替换操作。...比如: #define R 10 int main () { char *s = "Radio"; return 0; } •在第1行定义了一个叫R的宏,但是第4行中"Radio...所以在定义宏时,一般用一个小括号括住字符串的参数。...(10 * 10) / (2 * 2);,最后输出结果:25 5.与函数的区别 •1.从整个使用过程可以发现,带参数的宏定义,在源程序中出现的形式与函数很像。
,预处理之后产生的结果都放在test.i文件中。...所以用于对数值表达式进行求值的宏定义都应该用这种方式加上括号,避免在使用宏时由于参数中 的操作符或邻近操作符之间不可预料的相互作用。...#define 替换规则 在程序中扩展#define定义符号和宏时,需要涉及几个步骤。 在调用宏时,首先对参数进行检查,看看是否包含任何由#define定义的符号。...,除非加上括号,否则邻近操作符的优先级可能会产生不可预料的后果,所以建议宏在书写的时候多些括号。...函数参数只在函数调用的时候求值一次,它的结果值传递给函数。表达式的求值结果更容易预测。 带有副作用的参数 参数可能被替换到宏体中的多个位置,所以带有副作用的参数求值可能会产生不可预料的结果。
这⾥会出现语法错误。 2....#define定义宏 (1)定义 #define 机制包括了⼀个规定,允许把参数替换到⽂本中,这种实现通常称为宏(macro)或定义宏 (define macro)。...,这个问题便轻松的解决了~ #define SQUARE(x) (x) * (x) 所以⽤于对数值表达式进⾏求值的宏定义都应该⽤这种⽅式加上括号,避免在使⽤宏时由于参数中的操作符或邻近操作符之间不可预料的相互作...3.宏替换的规则 在程序中扩展#define定义符号和宏时,需要涉及⼏个步骤。 1. 在调⽤宏时,⾸先对参数进⾏检查,看看是否包含任何由#define定义的符号。...除⾮宏⽐较短,否则可能⼤幅度增加程序的⻓度。 2. 宏是没法调试的。 3. 宏由于类型⽆关,也就不够严谨。 4. 宏可能会带来运算符优先级的问题,导致程容易出现错。 5.
领取专属 10元无门槛券
手把手带您无忧上云