十一、C语言之宏定义

        在C语言中,#define 是预处理指令的一部分,用于定义宏。宏可以是一个简单的常量、一个带有参数的表达式或是一个代码块。使用宏可以在编译前替换代码中的特定部分,从而实现代码的重用、简化和提高可读性。

1、无参数宏定义

        无参数宏定义是最简单的形式,它只是一个标识符和一个值的组合。

/* 在代码中,每次出现PI,预处理器都会将其替换为3.14159。 */
#define PI 3.14159

2、带参数宏定义

        带参数宏定义允许接收一个或多个参数,并返回一个表达式。

/* SQUARE是一个宏,它接收一个参数x,并返回x的平方。
   注意,宏中的参数应该用括号括起来,以避免因为运算符优先级导致的问题。
 */
#define SQUARE(x)    ( (x) * (x) )

3、宏定义的代码块

        宏定义可以包含多个语句,这通常用于实现复杂的操作或内联函数。

/* SWAP 宏交换两个变量的值。*/

#define SWAP(a, b) do { \
    typeof(a) temp = a; \
    a = b; \
    b = temp; \
} while (0)
  • do-while循环
    • 条件始终为false(即0),所以循环体只会执行一次。
    • 使用do-while循环而不是简单的{}是为了确保宏可以像一个单独的语句那样使用,即使它被放在ifelse或其他控制语句中。
    • 如果你简单地使用{},那么当这个宏被放在if语句中时,可能会引发语法错误,因为if语句后面只能跟一个单独的语句。而使用do-while(0)可以确保宏在任何上下文中都能作为一个单独的语句使用。
      • 使用{} 的宏,再调用时后面不能有分号(;)
  • typeof( a ) temp = a;
    • typeof( a ) 是一个GNU C扩展(也被某些其他C编译器支持),用于获取变量a的类型。
    • 这行代码创建了一个临时变量temp,其类型与a相同,并将a的值赋给temp。

4、#undef

        可以使用#undef指令来取消一个宏的定义。

#define PI 3.14159
/* ... 使用 PI... */
#undef PI
/* 之后 PI 不再是一个宏 */

5、宏定义的注意事项

  • 宏定义只是简单的文本替换,没有类型检查或作用域限制。
  • 宏可能会因为参数的运算符优先级导致预期之外的行为,所以使用时要特别小心。
  • 宏定义可能会导致代码膨胀,因为每个宏的使用都会导致相同代码的重复插入。
  • 避免在宏中使用复杂的表达式或逻辑,因为这会增加代码阅读和维护的难度。
  • 使用宏时要谨慎,以避免出现意外的副作用或难以调试的错误。
  • 宏定义必须要先定义,再使用宏。
  • 宏定义还可以嵌套
    #define ADD(x, y) ((x) + (y))  
    #define DOUBLE(x) ((x) * 2)  
    
    // 使用嵌套宏定义  
    #define DOUBLE_OF_ADD(a, b) DOUBLE(ADD(a, b))  

6、内联系函数

(1)内联函数(Inline Functions)是C++中的一个特性,用于优化函数调用。当函数被声明为内联时,编译器会尝试在调用点将函数的代码直接插入,而不是进行常规的函数调用(即压栈、跳转、返回等步骤)。这样做可以减少函数调用的开销,提高程序的执行效率。

(2)示例:

#include <iostream>  
  
// 使用inline关键字声明内联函数  
inline int add(int a, int b) {  
    return a + b;  
}  
  
int main() {  
    // 在这里,add函数的代码可能会被直接插入到调用点  
    int sum = add(2, 3);  
    std::cout << "The sum is: " << sum << std::endl;  
      
    return 0;  
}

(3)内联函数优缺点及注意事项:

优点:

  • 提高执行效率:由于减少了函数调用的开销,内联函数可以提高程序的执行效率。

缺点:

  • 增加代码大小:由于编译器在调用点插入函数代码,这可能导致生成的代码文件变大。
  • 可能不是真正的内联:虽然函数被声明为内联,但编译器可能会选择不内联它,特别是当函数很大或很复杂时。
  • 滥用可能导致性能下降:如果过度使用内联函数,可能会导致代码膨胀和缓存失效,从而降低性能。

注意事项:

  • 不是所有函数都适合内联:通常,只有小型且频繁调用的函数才适合内联。大型函数或很少调用的函数可能不适合内联。
  • 内联是建议性的:虽然函数被声明为内联,但编译器可以选择不内联它。因此,内联是一种建议性的优化,而不是强制性的。
  • 内联函数通常定义在头文件中:由于内联函数需要在调用点插入代码,因此它们通常定义在头文件中,以便在多个源文件中可见。

(4)C语言内联函数

        在C语言中,并没有直接支持内联函数(inline functions)的语法,就像C++中的inline关键字那样。然而,许多C编译器(尤其是那些同时支持C和C++的编译器)可能会提供某种形式的内联函数支持作为扩展功能。但要注意的是,这些通常不是C语言标准的一部分,而是特定编译器的特性。

        在C语言中,优化函数调用的常用方法是确保函数非常小且简单,这样编译器可能能够自动进行内联优化,而无需显式地告诉它这样做。如果你正在使用支持内联函数扩展的C编译器(如GCC),你可以尝试使用__inline____inline关键字(两者都是GCC的内联函数扩展)。但请注意,这仍然不是C语言标准的一部分,因此它可能不会在所有C编译器上工作。

        下面是一个使用GCC内联函数扩展的示例:

__inline__ int add(int a, int b) {  
    return a + b;  
}  
  
int main() {  
    int sum = add(2, 3);  
    return 0;  
}

总结:

  • C语言中,并没有直接支持内联函数的语法。
  • 有些C编译器支持内联函数的扩展。
  • C语言中使用#define宏定义代码块,效果类似内联函数。

  • 11
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

代码织梦师小猪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值