一、背景:函数在源代码->预处理->编译和优化->生成目标文件->链接->可执行程序或镜像文件时。
函数的存在形式:
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语言中实现:
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函数:
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函数:
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
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++编译器严格类型检查的好处,另外它的返回值也不能被强制转换为可转换的合适的类型。