如果函数声明为
static char *function(...) { ... }
这是否意味着这是一个返回static char *
的非静态函数,或者是一个返回非静态char *
的静态函数?
比较以下两个功能。哪一个是正确的用途?
static char *fn1(void)
{
static char s[] = "hello";
return s;
}
static char *fn2(void)
{
char *s = malloc(6);
strcpy(s, "world");
return s;
}
答案 0 :(得分:8)
static
适用于函数,而不适用于其返回类型。这两个功能都是正确的 - 区别在于s
首次拨打fn1
时会初始化一次,而fn1
的所有来电都会共享s
;而在fn2
中,每次通话都会分配一个新的s
。由于fn1
和fn2
都有static
个链接,因此它们对于定义它们的翻译单元(大约是源文件)是私有的。
答案 1 :(得分:3)
你的两个函数定义都是正确的。
需要注意的是,static
这里用于将函数限制为文件范围,而不是指定返回类型,即,此函数可以由同一文件中存在的其他函数[调用]使用,但不是通过其他文件中存在的函数,尽管它们可能已被编译并链接在一起形成二进制文件。
答案 2 :(得分:3)
static
在函数应用于函数之前,而不是它的类型(或者甚至是它的一部分,如返回类型):
这意味着该函数具有静态链接,也就是翻译单元/文件本地(因此很可能被内联)。
这两个函数都是正确的,尽管它们有不同的语义:
free
它。答案 3 :(得分:1)
与函数定义一起使用时,static
关键字表示该函数具有文件级范围。这意味着函数名称仅在文件本身中可见。函数定义中使用的static
关键字修改函数名称可见性,不修改函数返回类型。
因此声明为static的函数可以返回任何类型的函数。
在函数体中定义的变量上使用static
用于指示在加载和启动应用程序时创建变量。因此,如果对函数中的变量使用static
修饰符,则在调用函数时不会在堆栈上创建该变量。它独立于调用函数时存在。但是,变量的可见性仅在函数内。
在您的示例中,您有一个返回static
变量地址的函数。你可以这样做,但你必须明白这个用途不是线程安全的。换句话说,调用该函数的所有线程将在相同的内存位置获取相同的变量,而不是它们自己的变量版本。
您还必须明白,如果您返回static
变量的地址,也会导致重入和递归问题。原因是堆栈上的变量提供了重入和递归,因为每次调用函数时,都会向堆栈添加一个新帧,因此每个函数调用都有自己的堆栈帧,因此它有自己的变量集。
这是标准C库中旧strtok()
函数的已知问题,它使用strtok()
函数中的变量来维护调用之间的状态,使用NULL作为最后一个字符串的地址解析字符串时调用strtok()
。我已经看到一个问题,一个名为strtok()
的函数开始解析一个字符串,然后调用另一个函数,该函数又调用strtok()
来开始解析一个不同的字符串。结果是一些非常奇怪的错误和行为,直到找到原因。
在文件中的全局变量上使用static
修饰符将创建一个可由文件中的多个函数共享的全局变量。但是,如果在函数名称上使用static修饰符,static
变量将只具有文件范围可见性。
// .. top of a file of C source code
static int aStaticInt = 0; // a static int that can be shared by all functions in the file but is visible only in the file
int aNonStaticInt = 0; // a non static int that is visible outside of the file
static int myStaticFunc (void)
{
// a function that is visible only within the file
}
int myNonStaticFunc (void)
{
// a function that is visible outside the file as well as inside the file
}