当前位置:  开发笔记 > 程序员 > 正文

何时"内联"无效?(在C中)

如何解决《何时"内联"无效?(在C中)》经验,为你挑选了4个好方法。

有些人喜欢使用inline关键字C,并在标题中添加大功能.你什么时候认为这是无效的?我认为它有时甚至很烦人,因为它很不寻常.

我的原则是inline应该用于非常频繁访问的小函数,或者用于实际类型检查.无论如何,我的品味指导我,但我不知道如何最好地解释为什么inline对大功能不那么有用的原因.

在这个问题中,人们建议编译器可以更好地猜测正确的事情.这也是我的假设.当我尝试使用这个参数时,人们回复它不适用于来自不同对象的函数.好吧,我不知道(例如,使用GCC).

谢谢你的回答!



1> Richard..:

inline 做两件事:

    为您提供"一个定义规则"的豁免(见下文).这始终适用.

    为编译器提供一个提示以避免函数调用.编译器可以自由地忽略它.

#1可能非常有用(例如,如果短,则将标题放在标题中),即使#2被禁用也是如此.

在实践中,编译器通常会更好地确定自己内联的内容(特别是如果可以使用配置文件引导优化).


[编辑:完整参考文献和相关文字]

以上两点均遵循ISO/ANSI标准(ISO/IEC 9899:1999(E),通常称为"C99").

在§6.9"外部定义"中,第5段:

一个外部定义为外部声明,这也是一个功能(比内联定义其他)或对象的定义.如果在表达式中使用通过外部链接声明的标识符(而不是作为sizeof运算符的操作数的一部分,其结果是整数常量),则整个程序中的某个地方应该只有一个标识符的外部定义; 否则,不得超过一个.

虽然C++中的等价定义明确地命名为单定义规则(ODR),但它具有相同的用途.外部(即不是"静态",因此对于单个翻译单元本地 - 通常是单个源文件)只能定义一次,除非它是函数内联.

在§6.7.4,"函数说明符"中,定义了内联关键字:

使函数成为内联函数表明对函数的调用尽可能快.[118]这些建议有效的程度是实施定义的.

脚注(非规范性),但提供了澄清:

例如,通过使用通常的函数调用机制的替代方法,例如"内联替换".内联替换不是文本替换,也不是创建新函数.因此,例如,在函数体内使用的宏的扩展使用它在函数体出现时的定义,而不是调用函数的位置; 和标识符指的是身体发生范围内的声明.同样,该函数具有单个地址,而不管除外部定义之外还发生的内联定义的数量.

简介:C和C++的大多数用户对内联的期望并不是他们得到的.其明显的主要目的是避免功能调用开销,这是完全可选的.但是为了允许单独编译,需要放宽单一定义.

(所有重点都在标准的引用中.)


编辑2:几点说明:

外部内联功能有各种限制.您不能在函数中使用静态变量,也不能引用静态TU范围对象/函数.

刚刚在VC++的" 整个程序优化 "中看到了这一点,这是编译器执行自己的内联事务而非作者的一个例子.



2> SingleNegati..:

内联声明的重要之处在于它不一定做任何事情.在许多情况下,编译器可以自由决定内联未声明的函数,并链接内联声明的函数.



3> Trevor Boyd ..:

一个例子来说明内联的好处.sinCos.h:

int16 sinLUT[ TWO_PI ]; 

static inline int16_t cos_LUT( int16_t x ) {
    return sin_LUT( x + PI_OVER_TWO )
}

static inline int16_t sin_LUT( int16_t x ) {
    return sinLUT[(uint16_t)x];
}

在做一些重数字运算并且你想避免在计算sin/cos时浪费周期时你用LUT替换sin/cos.

当你没有内联编译时,编译器不会优化循环,输出.asm将显示以下内容:

;*----------------------------------------------------------------------------*
;*   SOFTWARE PIPELINE INFORMATION
;*      Disqualified loop: Loop contains a call
;*----------------------------------------------------------------------------*

当您使用内联进行编译时,编译器会了解循环中发生的情况并进行优化,因为它确切地知道发生了什么.

输出.asm将具有优化的"流水线"循环(即它将尝试充分利用所有处理器的ALU并尝试保持处理器的流水线完整而没有NOPS).


在这个特定的情况下,我能够将我的表现提高大约2倍或4倍,这使我在实际截止日期之前得到了我所需要的.


ps我正在研究定点处理器...而像sin/cos这样的任何浮点运算都会影响我的性能.



4> quinmars..:

对于大型函数,不应该使用内联的另一个原因是库的情况.每次更改内联函数时,您可能会失去ABI兼容性,因为针对旧标头编译的应用程序仍然内联旧函数版本.如果将内联函数用作类型安全宏,那么在库的生命周期中永远不需要更改函数的可能性很大.但是对于大功能而言,这很难保证.

当然,只有当函数是您的公共API的一部分时,此参数才适用.

推荐阅读
家具销售_903
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有