嵌入式C基础——inline的作用

本期主题:
讲解inline的作用,并用实例来掩饰:

  1. 什么是inline,为什么要用inline
  2. 简单例子
  3. 实践中inline的使用方式

往期链接:



1. inline的作用

我们经常能看到形如这样的代码:

static inline void xxxx(xxx)
{
....
}

inline的作用是这样的:

在C语言中,inline 用于告诉编译器尝试将函数的代码插入到调用它的地方,而不是生成一个函数调用

那么使用inline与传统的函数调用相比,有哪些好处呢?

总结一下使用inline的好处如下:

  1. 性能优化: 内联函数可以减少函数调用的开销,因为它会直接将函数的代码插入到调用处,避免了函数调用时的参数传递、栈帧保存和恢复等操作。这对于频繁调用的小型函数特别有效,可以提高程序的执行效率。
  2. 减少函数调用开销: 函数调用会导致栈帧的建立和销毁,以及跳转到函数的代码位置,这些都会带来一定的性能开销。通过内联函数,可以避免这些开销,从而提高程序的性能。
  3. 编译器优化: 内联函数使得编译器更容易进行优化。在内联函数中,编译器可以更好地进行函数内联、常量折叠、循环展开等优化操作,从而生成更高效的代码。
  4. 避免宏的缺点: 内联函数可以避免使用宏带来的一些问题,比如宏的参数可能会被多次计算、宏的作用域可能会引起命名冲突等。内联函数在语法上更加清晰、安全,并且可以进行类型检查和错误检查。

总的来说,内联函数是一种优化手段,适合于频繁调用、函数体较小的情况下,可以提高程序的性能和可读性。但在使用内联函数时,也需要注意不要滥用,否则可能会导致代码膨胀、可维护性下降等问题。

2. 实例测试

看一个具体例子,用inline和不用inline的耗时对比,运行同一段简单的程序

#include <stdio.h>
#include <time.h>
// #include "add_inline.h"
#define LOOP_TIMES 10000000

// 非内联加法函数
int add(int a, int b) {
    return a + b;
}

// 内联加法函数
static inline int add_inline(int a, int b) {
    return a + b;
}

long long get_current_time_us() {
    struct timespec current_time;
    clock_gettime(CLOCK_MONOTONIC, &current_time);
    return current_time.tv_sec * 1000000LL + current_time.tv_nsec / 1000LL;
}

int main(void)
{
	int a, b;
	int time_cost = 0;
	
	long long start_time = get_current_time_us();
	for (int i = 0; i < LOOP_TIMES; i++) {
		add(a, b);
	}
	long long end_time = get_current_time_us();
	
	long long execution_time_us = end_time - start_time;
    printf("No inline Execution time (us): %lld\n", execution_time_us);

	start_time = get_current_time_us();
	for (int i = 0; i < LOOP_TIMES; i++) {
		add_inline(a, b);
	}
	end_time = get_current_time_us();
	
	execution_time_us = end_time - start_time;
    printf("Inline Execution time (us): %lld\n", execution_time_us);

	
	return 0;
}

运行结果:

$ ./a.out
No inline Execution time (us): 23235
Inline Execution time (us): 21733

从结果可以看出,inline的方式确实时间会更短一些。

3. inline的使用技巧

总结一下inline的使用技巧:

  1. inline修饰的函数一般适合放在头文件中:这是因为内联函数的本质是在调用点直接插入函数体,因此编译器需要在每个调用点都能够看到函数的定义,以便进行内联。
  2. 小型函数: 内联函数适合用于函数体较小的情况。一般来说,函数的代码应该足够简短,以便于被内联到调用处,避免代码膨胀。
  3. 频繁调用: 内联函数适合用于被频繁调用的函数。因为内联函数可以减少函数调用的开销,对于频繁调用的函数可以提高程序的性能。
  4. 避免函数调用开销: 内联函数适合用于需要避免函数调用开销的情况。比如,在性能敏感的代码中,可以将一些关键的函数标记为内联,从而减少函数调用带来的性能损失。
  5. 简单数据类型: 内联函数适合用于处理简单数据类型的情况。对于复杂的数据类型或者涉及到大量计算的函数,内联可能并不适合,因为内联会导致代码膨胀。
  6. 短小明了的代码: 内联函数适合用于代码逻辑简单明了的情况。内联函数的定义应该清晰易懂,不涉及复杂的逻辑或控制流程。
  7. 避免滥用: 内联函数应该谨慎使用,避免滥用。过度使用内联函数可能会导致代码膨胀、可读性下降等问题,应该根据实际情况进行权衡。
  • 9
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值