我正在使用C语言并修改以前由其他人编写的代码。我正在努力解决一些问题,而且我正在努力尽可能多地了解正在发生的事情。因此,正如我的问题所述,创建函数时static inline void
和void
之间的区别是什么?我为这篇长篇文章提前道歉,但我想让你知道我做了一些研究,但不明白我发现了什么。
我发现an explanation of 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
}
答案 0 :(得分:13)
static
表示无法从另一个编译单元(源文件)引用它。 "引用的"通过名称调用或以其他方式引用的方式,例如分配给函数指针。
inline
向编译器暗示函数的代码应该在被调用的位置内联生成,而不是作为要分支的单独函数生成。这通常是出于性能原因而完成的。处理微软的报价:
如果函数的地址被采用或者如果是,则编译器不会内联函数 太大而无法内联。
内联函数没有地址,因为它不作为单独的实体存在。它的代码与它所调用的代码无缝地交织在一起。因此,如果你获取函数的地址(例如,指定给指针),那么编译器必须将其生成为实数函数,并且不能内联它。
void
表示函数不返回值。
查看了您的代码示例后,我猜测某处有一个单独的CGauss()
定义,正在从 file1.c 调用,而 file2.c 正在调用自己的私有版本。或者 file1.c 是#include
file2.c 。哪个会讨厌。
答案 1 :(得分: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
关键字只是推动编译器内联某些函数。根据自己的判断,它可能会或可能不会实际执行。
答案 2 :(得分:2)
静态关键字
定义一个C函数静态意味着(正如文档所说)这个函数只能从它定义的源文件中访问。这个术语“引用”意味着调用这个函数或者例如取一个函数指向它的指针。
<强>内联强>
通常,当您在C中编写函数时,编译器会为此函数生成机器代码:
foo:
/* some machine code */
ret
每次调用此函数时,编译器都会插入一条指令,如
call <foo>
进入调用者的机器代码,这意味着“跳转到foo,执行你在那里找到的内容,当你遇到ret指令时,返回到这个位置。”
相反,对于内联函数,编译器不会生成单独的函数foo(),而是将函数foo的机器代码插入到每个调用站点中。执行此代码时,这具有相同的效果。
为什么我们这样做?内联代码的优点是可以节省两次跳转(调用和相应的ret),这使得代码执行速度更快。作为缺点,您的代码会变大,因为您在每个调用站点上插入机器代码而不是只有一个可调用函数的副本。这就是为什么你通常只能内联小函数。
此外,您不能将函数指针带入内联函数,并且调试变得更难,因为您无法轻松地在内联函数上设置断点。
因此,内联留给编译器作为优化选项,并使用关键字,如C ++的内联,内联指令或GCC的__attribute ((内联)),您只需要给编译器暗示内联可能值得一试。
答案 3 :(得分:0)
static只意味着本质上该函数的所有意图和目的在其定义的源文件之外是“不可见的”。
内联要求编译器基本上将函数调用代码直接放入函数在编译时被调用的每个位置的源中(比如用函数代码替换函数调用) - 但是,它不能保证它发生了,它只是建议你的编译器。
它比技术更具技术性,你可能会得到更好的答案,但用简单的语言来说这就是术语的含义。
答案 4 :(得分:0)
我想补充以上所有内容,在阅读上述内容之前,了解c编程的工作原理非常重要。 如果你只是编写开放代码,比如
Setup(){
int MainVar
}
MyRoutine(){
int myVar1;
int myVar2;
bool myVar3;
// Do stuff with myVars
MainVar = myVar1 - myVar2;
myVar3 = true;
}
然后任何人都可以直接从第二个程序访问MyRoutine.myVar1。他们可以改变myVar2的值,(1。如果它不受保护,2。如果他们知道它在那里,3。如果他们知道它做了什么),然后在MyRoutine中使用//做东西,从而改变了什么原始程序员打算。
想象一下,您正在编写银行业务程序并使代码容易受到攻击,因此有人可以更改DEPOSIT的值,而无需在例程中更改其他银行的WITHDRAWL。其他人可以出现并编写一个单独的程序来将该值更改为2或10,并在不存在的情况下创建资金。但是,如果您在代码,例程,方法或变量之前使用STATIC那些项目无法被其他程序访问,查看和最重要的更改。
您可以在任何时候使用Static,使整个例程CLOSED,或仅使用CLOSED个别变量。因此,允许其他人对代码的某些方面进行更改,但保留那些需要保护的方面。
将静态放在MyRoutine会阻止某人从另一个程序执行MyRoutine。由于MyVars是在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;
}
答案 5 :(得分:-1)
这是如此简单。
void*
可以返回空指针(任何引用)。
但是void
不能返回任何东西。
例如:
int x=7;
void *abc()
{
return &x;
}
int main()
{
printf("%d\n",*((int*)(abc())));
}
输出:7
int x=7;
void abc()
{
return &x;
}
int main()
{
printf("%d\n",*((int*)(abc())));
}
它将在printf("%d\n",*((int*)(abc())));
处产生编译错误
因为void
无法返回任何内容。