17

我正在使用 C 语言并修改以前由其他人编写的代码。我在一些事情上苦苦挣扎,我试图尽可能多地了解正在发生的事情。static inline void那么,正如我的问题所述,创建函数之间和void创建函数时有什么区别?我提前为这篇长文道歉,但我想让你知道我确实做了一些研究,但不明白我发现了什么。

我发现了一个让我困惑的解释static

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

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

通过同一个网站,他们解释了内联函数,我不明白这是什么意思。

__inline 关键字告诉编译器将函数定义中的代码替换为函数调用的每个实例。但是,替换仅由编译器自行决定。例如,如果函数的地址被占用或太大而无法内联,则编译器不会内联函数。

啊???

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

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

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

以下位于file2.c中

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

6 回答 6

16

static意味着它不能被另一个编译单元(源文件)引用。“引用”是指被调用或以其他方式引用的名称,例如分配给函数指针。

inline是对编译器的一个提示,即函数的代码应该在调用它的地方内联生成,而不是作为要分支到的单独函数生成。这通常是出于性能原因。处理微软的报价:

如果函数的地址被占用或太大而无法内联,则编译器不会内联函数。

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

void表示函数不返回值。


查看您的代码示例后,我猜想CGauss()某处有一个单独的定义,它是从file1.c调用的,而file2.c正在调用它自己的私有版本。要么,要么file1.c#includeing file2.c。这会很讨厌。

于 2012-06-12T14:44:44.547 回答
8

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关键字只是推动编译器内联某些函数。它可能会或可能不会真正做到,这取决于它自己的判断。

于 2012-06-12T14:43:50.240 回答
3

静态关键字

定义一个 C 函数静态意味着(如文档所说)该函数只能从定义它的源文件中访问。在这种情况下,术语“引用”意味着调用此函数或例如获取指向它的函数指针.

内联

通常,当您用 C 编写函数时,编译器会为该函数生成机器码:

foo:
   /* some machine code */
   ret

每次调用此函数时,编译器都会插入一条指令,例如

  call <foo>

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

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

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

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

因此,内联留给编译器作为优化选项,通过使用诸如 C++ 的 inline、您的inline 指令或 GCC 的 __attribute ((inline)) 之类的关键字,您只会向编译器提示内联可能值得在这里尝试.

于 2012-06-12T14:48:47.447 回答
1

我想补充以上所有内容,在阅读以上内容之前,了解 c 编程的工作原理很重要。如果您只是编写开放代码,例如

Setup(){
    int MainVar
}

MyRoutine(){
   int myVar1;
   int myVar2;
   bool myVar3;
   // Do stuff with myVars
   MainVar = myVar1 - myVar2;
   myVar3 = true;
}

然后任何人都可以直接从第二个程序访问 MyRoutine.myVar1。他们可以在 MyRoutine 中使用它之前更改 myVar2 的值,(1. 如果它不受保护,2. 如果他们知道它在那里,3. 如果他们知道它的作用)//Do stuff,从而改变了什么原程序员打算。

想象一下,您正在编写一个银行程序,并且让代码易受攻击,因此有人可以更改存款的价值,而无需在您的例程中更改来自另一家银行的 WITHDRAWL。其他人可能会出现并编写一个单独的程序来将该值更改 2 或 10,并在不存在的地方创造货币。但是,如果您在代码、例程、方法或变量之前加上 STATIC,则这些项目不能被另一个程序访问、查看和最重要的更改。

您可以在任何时候使用静态,使整个例程关闭,或仅关闭单个变量。因此允许其他人对您的代码的某些方面进行更改,但保留那些需要保护的方面。

在 MyRoutine 中设置静态会阻止某人从另一个程序执行 MyRoutine。由于 MyVar 是在 MyRoutine 中声明的,因此无法从其他程序访问它们。但是如果在程序的其他地方声明了一个名为 MainVar 的变量,它就可以访问。

Setup(){
    int MainVar  // This can be accessed from outside this code
}

static MyRoutine(){  // Because of static these vars are not
   int myVar1;
   int myVar2;
   bool myVar3;
   // Do stuff with myVars
   MainVar = myVar1 - myVar2;
   myVar3 = true;
}

在这里,只有带有静态的变量受到保护。myVar3 可以从其他地方读取,通知另一个例程交换已完成。

Setup(){
    int MainVar    // This can be accessed from outside this code
}

MyRoutine(){
   static int myVar1;  // This can NOT be accessed from outside this code
   static int myVar2;  // This can NOT be accessed from outside this code
   bool myVar3;        // This can be accessed from outside this code
   // Do stuff with myVars
   MainVar = myVar1 - myVar2;
   myVar3 = true;
}
于 2018-05-20T20:59:58.537 回答
0

静态只是意味着本质上该函数在定义它的源文件之外用于所有意图和目的“不可见”。

inline 要求编译器在编译时调用函数的每个位置将函数调用代码直接替换到源代码中(例如用函数代码替换函数调用) - 但是,不能保证会发生,它只是向您的编译器建议它。

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

于 2012-06-12T14:46:14.967 回答
-2

就是这么简单。

void*可以返回一个 void 指针(任何引用)。但void不能退任何东西。

例如:

1)

int x=7;

void *abc()    
{    
    return &x;    
}     

int main()    
{    
    printf("%d\n",*((int*)(abc())));    
}

输出:7

2)

int x=7;

void abc()    
{    
    return &x;    
}

int main()    
{    
    printf("%d\n",*((int*)(abc())));    
}

它将产生编译错误printf("%d\n",*((int*)(abc())));

因为void不能退货。

于 2019-01-06T00:39:41.857 回答