回 帖 发 新 帖 刷新版面

主题:[讨论]内联函数,一般函数,宏的透彻理解,所有人进


一本书上说:
调用内联函数时,编译系统直接将内联函数代码替换到主函数调用的地方,而普通函数则是通过参数传递。
    那内联函数不和宏替换一样了吗?
    那内联函数会不会遇到和宏一样的问题
例如以下是一个用内联函数实现的代码:
(我用的Dev)
#include<stdio.h>
#include<stdlib.h>
inline int sq(int);
int main()
{
     int i=1;
     while(i<=5)printf("%d ",sq(i++));
     printf("\n");
                
     system("PAUSE");
     return 0;
     }
inline int sq(int y)
{
    return (y)*(y);
}
运行结果为1 4 9 16 25




这个是用宏实现的
#include<stdio.h>
#include<stdlib.h>
#define sq(y) ((y)*(y))
int main()
{
     int i=1;
     while(i<=5)printf("%d ",sq(i++));
     printf("\n");
                
     system("PAUSE");
     return 0;
     }
运行结果为1 9 25   原因是宏替换时(i++)*(i++)每次i都自增了两次


有人说内联有点类似   那它们会遇到相同的问题吗?(在我举的例子中没有遇到,也许是没有内联编译系统把它当一般函数处理了,所以和大家讨论一下)

它们有区别吗?

回复列表 (共12个回复)

11 楼

大部分情况下(基本是应用层)编译器会做的更好。我之所以指出这个属性,是因为内核以及驱动里有很多时候要强制内联,因为linux内核(特别是嵌入式平台)的栈空间是极小的,由内核和驱动模块共用。编译器考虑不到这些特殊情况。
另外说句题外话,编译器所做的优化只是一方面,所谓static scheduling。另一方面取决于处理器本身的调度,即dynamic scheduling。这一层是微码级别调度,我们团队平时设计ISA结构芯片的时候,这个流水线调度是重点,要结合很多东西,比如分支预测硬件,trace cache, MOB以及ROB。

12 楼

[quote]大部分情况下(基本是应用层)编译器会做的更好。[/quote]确实是这样的:)[quote]我之所以指出这个属性,是因为内核以及驱动里有很多时候要强制内联,因为linux内核(特别是嵌入式平台)的栈空间是极小的,由内核和驱动模块共用。编译器考虑不到这些特殊情况。[/quote]我确实忽略了这些极端情况了,不过以前我是这样做的:把返回地点放到寄存器或是特定地点,然后jmp到特定的代码段执行,需要“返回”时再jmp到那个地址,以此来减少栈使用~~~~[quote]
另外说句题外话,编译器所做的优化只是一方面,所谓static scheduling。另一方面取决于处理器本身的调度,即dynamic scheduling。这一层是微码级别调度,我们团队平时设计ISA结构芯片的时候,这个流水线调度是重点,要结合很多东西,比如分支预测硬件,trace cache, MOB以及ROB。[/quote]确实,就算是应用层其实也会遇到这些问题,对于高性能应用,往往也需要了解一些如指令配对、条件分支替代等问题。虽然并不要求每个人都写这样的代码,但了解总是有益处的:)

PS:近期难得见大牛们回归啊:)

我来回复

您尚未登录,请登录后再回复。点此登录或注册