zoukankan      html  css  js  c++  java
  • 语言之内联函数

    一、背景:函数在源代码->预处理->编译和优化->生成目标文件->链接->可执行程序或镜像文件时。

      函数的存在形式:

      1.1.普通函数:在编译时是将函数代码放在指定位置,其他函数调用此函数时,进行跳转地址,参数通过寄存器进行传递。

      1.2.内联函数:在预处理时将函数体代码直接替换函数调用处,不进行跳转地址,不进行参数通过寄存器进行传递。(实质与宏定义一样)

      注意:能否形成内联函数,需要看编译器对该函数定义的具体处理。(C99和GNU C支持)

    二、特点与环境

      2.1.1.优点

        消除函数调用和返回所带来的开销(寄存器存储和恢复),且编译器会将调用函数的代码和函数本身一起进行优化。

      2.1.2.缺点

        代码变长,占用更多的内存空间或者占用更多的指令缓存。

      2.2.1.适用环境

        对时间要求较高,长度较短的函数。

      2.2.2.不适用环境

        函数较大,反复被调,时间上无特殊限制。

    三、内联C格式

      内联函数是指用inline关键字修饰的函数。

      一般在头文件中定义,如果一个内联函数仅在某个源文件中使用,也可以定义在该文件的开始处。

      且前缀static(编译时不会为内联函数单独建立一个函数体)

      3.1.C语言中实现

     C++ Code 
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    static inline void acodec_regsetbit(
        
    unsigned long value,
        
    unsigned long offset,
        
    unsigned long addr)
    {
        
    unsigned long t, mask;

        mask = 
    1 << offset;
        t = readl(addr);
        t &= ~mask;
        t |= (value << offset) & mask;
        writel(t, addr);
    }

      3.2.C++中实现

        3.2.1.类中定义inline函数

     C++ Code 
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    class ClassName
    {
        .....
        ....
        INT GetWidth()
        {
            
    return m_lPicWidth;
        }; 
    // 如果在类中直接定义,不需要用inline修饰,编译器自动化为内联函数
        .... //此说法在《C++ Primer》中提及
        ....
    }

         3.2.2.类外定义inline函数

     C++ Code 
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    class Account {
    public:
    Account(
    double initial_balance) { balance = initial_balance; } //与1相同
    double GetBalance(); //在类中声明
    double Deposit( double Amount );
    double Withdraw( double Amount );
    private:
    double balance;
    };
    inline double Account::GetBalance() { return balance; } //在类外定义时添加inline关键字
    inline double Account::Deposit( double Amount ) { return ( balance += Amount ); }
    inline double Account::Withdraw( double Amount ) { return ( balance -= Amount ); }

        注意:

        1.inline说明对编译器来说只是一种建议,编译器可以选择忽略这个建议。比如,你将一个长达1000多行的函数指定为inline,编译器就会忽略这个inline,将这个函数还原成普通函数。
        2、在调用内联函数时,要保证内联函数的定义让编译器"看"到,也就是说内联函数的定义要在头文件中,这与通常的函数定义不一样。但如果你习惯将函数定义放在CPP文件中,或者想让头文件更简洁一点,可这样做:
     C++ Code 
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    #ifndef SOMEINLINE_H
    #define SOMEINLINE_H
    Type Example(
    void);
    //........其他函数的声明
    #include"SomeInlie.cpp" //源文件后缀名随编译器而定
    #endif
    //SomeInline.cpp中
    #include"SomeInline.h"
    inline Type Example(void)
    {
    //..........
    }
    //...............其他函数的定义

    四、内联汇编

      4.1.前提

        知道对应体系结构,才能使用此功能。

      4.2.格式

        asm volatile(“....”);

        举例:

          asm volatile("rdtsc" : "=a" low, "=d" (high));

      4.3.适用环境

        偏近体系结构的底层或对执行时间要求严格。

    五、产生原因

      优点:

        C语言是一个效率很高的语言,这种宏定义在形式及使用上像一个函数,但它使用预处理器实现,没有了参数压栈,代码生成等一系列的操作,因此,效率很高。

        C++中引入了类及类的访问控制,这样,如果一个操作或者说一个表达式涉及到类的保护成员或私有成员,你就不可能使用这种宏定义来实现(因为无法将this指针放在合适的位置)。为了取代这种表达式形式的宏定义,inline消除了宏定义的缺点,同时又很好地继承了宏定义的优点。

      缺点:

         因为实际操作为预处理器符号表中的简单替换,因此它不能进行参数有效性的检测,也就不能享受C++编译器严格类型检查的好处,另外它的返回值也不能被强制转换为可转换的合适的类型。

  • 相关阅读:
    python3笔记-列表
    python3笔记-字典
    MD侧滑
    SnackBar使用
    TextIInputLayout使用
    Toolbar与SearchView
    Palette使用
    TabLayout使用
    沉浸式-体验
    沉浸式-兼容优化
  • 原文地址:https://www.cnblogs.com/pokerface/p/7768245.html
Copyright © 2011-2022 走看看