2012-06-12 94 views
13

我正在使用C语言并修改以前由其他人编写的代码。我正在努力处理一些事情,我尽可能地了解我所能做的事情。所以,正如我的问题所述,创建函数时static inline voidvoid之间有什么区别?我为这篇长文章事先道歉,但我想让你知道我做了一些研究,但不明白我发现了什么。静态内联void和void之间有什么区别?

我发现an explanation of static是混淆了我:

static声明表示该功能不能被引用的其他文件 ;也就是说,链接器不会导出该名称。

通过阅读本文,我假设引用函数不同于调用函数?我假设因为这个函数是从另一个.c文件中调用的。如果是这样的话,什么是引用一个函数?

通过相同的网站,他们解释inline functions,我不明白这是什么意思。

__inline关键字告诉编译器用 内的代码替换每个函数调用实例的函数定义。 但是,替换只能由编译器自行决定。例如,对于 示例,如果编译器的地址是 ,或者它太大而不能内联,则编译器不会内联函数。

呃???

任何帮助非常感谢,我再次为这个非常长的帖子道歉。

位于file1.c中(使用通用名称,因为我不认为它很重要)以下

COMPLEX cNoiseSample; 
CGauss(&cNoiseSample, loopbackRadio->pState); 

位于file2.c中

static inline void CGauss(COMPLEX * pcGauss, P_OS_UNIFORM_RAND_STATE pState) 
{ 
    //code 
} 

回答

12

static表示不能从其他编译单元(源文件)引用它。 “被引用”是指被称为,或以其他名称引用,例如,分配给一个函数指针。

inline是编译器提示函数的代码应该在被调用的位置内联生成,而不是生成为要分支的独立函数。这通常是出于性能原因。要处理微软的报价:

如果编译器的地址被采用或者它的内存太大而不能内联,编译器不会内联函数。

内联函数没有地址,因为它不作为单独的实体存在。它的代码与它所调用的代码无缝地交织在一起。所以,如果你把一个函数的地址(例如分配给一个指针),那么编译器必须将它生成为一个真实函数,并且不能内联它。

void表示函数不返回值。


说完看着你的代码示例,我猜想,有一种CGauss()某处单独的定义,它正在从file1.c中叫,而file2.c中呼吁自己的私人版。或者,或者file1.c#include ing file2.c。这将是讨厌的。

+0

另外,'inline'对于在包含在不同编译单元中的头文件中定义一个函数时强制执行一个定义规则是必要的(或者至少对于C++来说是这样,不完全知道C中的这个细节,I想象它会是一样的) – rubenvb

+0

嗯,我想我比@ Graham-Borland有点困惑。让我告诉你为什么:COMPLEX cNoiseSample; CGauss(&cNoiseSample,loopbackRadio-> pState);/*这段代码在.c源文件中的一个点处调用,而在另一个.c源文件中调用。我有这个:*/static inline void CGauss(COMPLEX * pcGauss,P_OS_UNIFORM_RAND_STATE pState)/ *我为糟糕的格式化道歉在评论框中,不知道该怎么做。*/ – TZPike05

+0

编辑你的问题,粘贴那里的代码片段。 –

6
以下

static只有当您有多个源文件时才有意义。它指定static函数或变量不能从不同文件中的函数访问。

inline是一种编译器优化,可在某些情况下加快代码的速度。每当你调用一个函数时,都会有一些相关的开销。因此,编译器可以通过复制+粘贴(几乎)内联代码来完全摆脱该函数。

这里是内联的例子:

int dotproduct(int x1, int y1, int x2, int y2) { 
    return multiply(x1,x2)+multiply(y1,y2); 
} 

inline int multiply(int a, int b) { 
    return a*b; 
} 

编译器将它变成:

int dotproduct(int x1, int y1, int x2, int y2) { 
    return x1*x2+y1*y2; 
} 

如果你想成为幻想,你也可以内联dotproduct功能;)

请注意,inline关键字仅仅是编译器对特定函数的内联。根据自己的判断,它可能会也可能不会。

+0

谢谢@tskuzzy,内联使现在更有意义。 – TZPike05

0

静态只是意味着基本功能是用于所有意图和目的,它是在定义的源文件的外部“隐形”。

直列askes编译器基本上直接substite函数调用代码到源在编译时调用函数的每个地方(就像用函数代码替换函数调用一样) - 然而,它不保证会发生,它只是向您的编译器显示它。

它比这更技术化,你可能会得到更好的答案,但用简单的语言来说,这就是术语的含义。

2

static关键字

定义C函数静态装置(如文档说),该函数只能从源访问文件时,它在被定义。在此SENCE装置的术语“参考”要么调用这个函数,要么给函数指针指向它。

内联

通常情况下,当你写C中的函数,编译器生成该功能的机器代码:

foo: 
    /* some machine code */ 
    ret 

每次调用这个函数,编译器插入的指令如

call <foo> 

进入调用者的机器码,这意味着没有别的比“跳到foo,e执行你在那里找到的内容,当你遇到ret指令时,返回到这个位置。“

相比之下,对于内联函数,编译器不会生成单独的函数foo(),而是将函数foo的机器代码插入每个调用站点。执行此代码时,这具有相同的效果。

那么,我们为什么要这样做呢?内联代码的优点是可以节省两次跳转(调用和各自的ret),从而使代码执行速度更快。作为缺点,您的代码变得更大,因为您在每个呼叫站点上插入机器代码,而不是只有一个可调用函数的副本。这就是为什么你通常只会内联小函数。

此外,您不能将函数指针指向内联函数,并且调试变得更困难,因为您无法轻松地在内联函数上设置断点。

因此,内联留给编译器的优化选项,并通过使用关键字,如C++的内联,你inline指令,或GCC的__attribute((在线)),你只给编译器一个暗示,内联可能值得在这里尝试。

相关问题