C语言中__inline函数作用解释

本文探讨了C语言中inline函数的有效使用方法,包括最佳实践如限制代码行数、避免循环与条件语句等;同时介绍了inline函数在不同场景下的性能影响及编译行为。

C语言inline函数的使用方法2012-01-20 00:00 中国IT实验室 佚名 ..关键字:C语言   大学在教科书上学习过inline函数,定义为inline函数之后,会省去函数调用的开销,直接嵌套汇编代码,取代函数调用,提高效率。工作后项目中也很少用到inline来定义函数,近几天在研读google的google c++ style guide,发现之前自己对inline函数的认识太过肤浅了,这里学习总结一下。

  1、inline函数不要超过10行代码,且不能包含循环、switch、if语句

  2、在一个c文件中定义的inline函数是不能在其它c文件中直接使用,google推荐把inline函数定义在**-inl.h头文件中。

  3、不要过度使用inline函数定义,尤其对大函数来说

  上面三点说明如何正确的使用inline函数,我以前的时候对inline理解不透彻,使用inline的方式不正确,但现在编译器够先进,能保证错误的inline定义也可以正确编译、运行。可能会有性能的缺失。

  我在F14(gcc 版本 4.5.1 20100924 (Red Hat 4.5.1-4) (GCC))上做了个实验:

  1、当inline函数超过10行,并且包含了循环、switch语句后gcc会执行inline语义,将inline函数汇编嵌入到main函数中。

  //gcc n.c -O2 -S

  #include
  #include
  //inline int inc_inline(volatile int *j);

  inline int inc_inline(volatile int *j)

  {

  for (;*j < 100; (*j)++)

  {

  *j += 2;

  (*j)++;

  }

  switch (*j)

  {

  case 1:

  (*j)++;

  break;

  case 2:

  (*j)++;

  break;

  default:

  break;

  }

  return (*j)++;

  }

  int main(int argc, char *argv[])

  {

  volatile int i = 0;

  inc_inline(&i);

  printf("i;%d\n", i);

  return 0;

  }

  2、当我把inline函数的定义放到另一个c文件中,在main函数文件中声明此函数,此时inline函数不生效,gcc编译出的汇编使用call进行正常的函数调用。

  //gcc n.c a.c -O2 -S

  3、当我们过度使用inline函数,会造成程序文件变大,性能降低。程序文件变大是肯定的,但为什么性能会降低呢,inline不是为了提高性能吗?使用的方式不正确性能不能提高,反而会下降。现在的CPU上都有cache,紧凑的代码在chache中保存的时间更长,这样cache命中的机会更高。

  如果某个A函数未定义为inline,并且被很多其它函数调用,那个这个A函数很大的可能会长期被保存在cahe中,这样CPU对代码的执行速度会提高很多。如果A函数被定义为了inline函数,代码分散各个调用函数中,这样每次指定都不命中都需要去内存把代码拷贝到cache中,然后执行,造成很大的抖动。

  更深一层的理解,当函数整个函数编译为的汇编代码,函数调用的上下文切换占用了大多的时间的时候,可以考虑把此函数定义为inline函数。


原文出自【比特网】,转载请保留原文链接:http://soft.chinabyte.com/database/25/12248025.shtml

<think>好的,我现在需要回答用户关于C语言中__asm__函数作用的问题。首先,我得回忆一下自己对__asm__的了解,可能还需要查阅一些资料来确保准确性。 我记得在C语言中,内联汇编允许在C代码中直接嵌入汇编指令,这样可以进行底层操作或者优化关键代码段。__asm__是GCC编译器中使用的一个关键字,用来插入汇编代码。不过,不同编译器可能有不同的语法,比如Visual C++使用__asm。用户提到的是__asm__,所以应该是指GCC的情况。 接下来,我需要明确__asm__的基本用法。通常,它的语法结构是__asm__后面跟汇编指令,可能还有输出、输入和破坏列表。例如: __asm__("汇编指令" : 输出操作数 : 输入操作数 : 破坏的寄存器); 然后,需要解释每个部分的作用。输出操作数是将汇编的结果传递给C变量,输入操作数则是将C变量传递给汇编代码,破坏列表告诉编译器哪些寄存器会被修改,以便编译器做好保护。 接下来,应该举一个简单的例子,比如实现两个数相加,或者访问特定的寄存器。比如使用cpuid指令来获取CPU信息,这可能需要使用eax寄存器作为输入输出,这时候内联汇编就很有用。 另外,需要提到使用内联汇编的注意事项,比如可移植性问题,因为不同架构的汇编指令不同;维护难度,因为汇编代码更难阅读;以及正确性问题,需要确保指令和约束正确,否则可能导致崩溃。 可能还需要区分__asm__和asm,在GCC中,当使用-std=c99等标准时,可能需要使用__asm__而不是asm,因为后者可能被保留或禁用。这也是一个需要注意的地方。 总结一下,回答的结构应该是:首先介绍__asm__的作用,然后详细说明其语法和组成部分,接着给出一个例子,最后讨论使用时的注意事项和常见问题。需要确保用中文清晰表达,并且符合用户提供的格式要求,比如数学公式的格式,但在这个问题中可能不太涉及数学公式,所以可能不需要特别处理。另外,要使用自然的口语化中文,避免使用Markdown格式,分步骤说明,让用户容易理解。</think>在C语言中,`__asm__` 是GCC编译器提供的内联汇编(Inline Assembly)功能的关键字,**用于直接在C代码中嵌入汇编指令**。以下是逐步说明: --- ### 1. **核心作用** - **直接控制硬件/底层优化**: 允许绕过C语言的抽象层,直接操作寄存器、CPU指令或执行特殊操作(如内存屏障、特权指令)。 - **性能关键代码优化**: 对时间敏感的代码段(如加密算法、内核代码),可通过汇编手动优化。 - **访问特殊功能**: 调用C语言无法直接实现的CPU指令(如`cpuid`、`rdtsc`)。 --- ### 2. **基本语法** ```c __asm__ ( "汇编指令" : 输出操作数列表 // 将汇编结果传递给C变量 : 输入操作数列表 // 将C变量传递给汇编代码 : 破坏列表 // 声明被修改的寄存器/内存 ); ``` --- ### 3. **示例:两数相加** ```c int a = 5, b = 10, result; __asm__ ( "addl %%ebx, %%eax;" // 汇编指令:eax = eax + ebx : "=a"(result) // 输出:将eax寄存器的值存入result : "a"(a), "b"(b) // 输入:a→eax, b→ebx : // 无破坏寄存器(假设未修改其他寄存器) ); // 最终 result = 15 ``` --- ### 4. **关键注意事项** - **编译器依赖**: `__asm__` 是GCC的语法,其他编译器(如MSVC)使用 `__asm`。 - **可移植性差**: 汇编代码与CPU架构绑定(x86、ARM等),更换平台需重写。 - **寄存器管理**: 需明确声明破坏列表(如`"eax", "memory"`),否则可能引发未定义行为。 - **优化干扰**: 不当使用可能阻止编译器优化(如寄存器分配)。 --- ### 5. **典型应用场景** - **系统级编程**: 操作CR0/CR4等控制寄存器(如启用分页)。 - **性能优化**: 手动展开循环或使用SIMD指令(如SSE/AVX)。 - **调试与诊断**: 插入`int3`断点指令或读取时间戳计数器(`rdtsc`)。 --- ### 6. **对比标准C的局限性** - C语言无法直接实现的功能: ```c // 读取CPU ID unsigned int eax_val; __asm__ ("cpuid" : "=a"(eax_val) : "a"(0) : "%ebx", "%ecx", "%edx"); ``` --- ### 7. **替代方案** - **编译器内置函数**: 如`__builtin_popcount()`(计算二进制1的个数),可替代部分汇编需求。 - **单独汇编文件**: 复杂汇编代码建议独立编写(.s或.S文件),通过链接器整合。 --- **总结**:`__asm__` 提供了C语言与汇编的混合编程能力,适用于底层操作和极端优化,但需谨慎使用以保证代码稳定性和可维护性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值