【问题标题】:C: how to declare a static function that returns a nonstatic string?C:如何声明一个返回非静态字符串的静态函数?
【发布时间】:2015-03-30 08:57:45
【问题描述】:

如果一个函数被声明为

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;
}

【问题讨论】:

  • static char * 不是类型
  • 其实void是多余的,会让一些编译器崩溃。
  • @Prof.Falken,我认为fn1(void),至少在C89 中,意味着我声明了一个不带参数的函数,而fn1() 意味着未指定参数(即,在没有发明原型的想法的旧时代)。我错了吗?
  • @TavianBarnes。感谢您的简洁回复!
  • 我不确定,但我认识到过去使用 void fn1(void) 的做法。是C89还是只是渎职,我不知道。但是我最近看到了一些编译器错误,可能是 Visual Studio。

标签: c function-prototypes


【解决方案1】:

static 适用于函数,而不是其返回类型。这两个函数都是正确的——区别在于s 将在第一次调用fn1 时初始化一次,而所有对fn1 的调用将共享s;而在fn2 中,每次调用都会分配一个新的s。由于fn1fn2 都具有static 链接,因此它们对于定义它们的翻译单元(大约是源文件)是私有的。

【讨论】:

    【解决方案2】:

    static 在函数应用于函数之前,而不是它的类型(甚至是它的一部分,如返回类型):
    这意味着该函数具有静态链接,也就是本地翻译单元/文件(因此很可能是内联的)。

    这两个函数都是正确的,尽管它们的语义不同:

    • 第一个返回指向静态数组的指针,其内容可能会被修改。但是,如果您这样做,请注意并发和重入问题。
    • 第二个分配一些堆内存,用一个字符串初始化它,然后返回它。记得free它。

    【讨论】:

      【解决方案3】:

      你的两个函数定义都是正确的。

      注意,这里的static是用来限制函数在文件范围内的,而不是指定返回类型,即这个函数可以被同一个文件中存在的其他函数使用[调用],但不能通过一些其他文件中存在的函数,尽管它们可能已被编译并链接在一起以形成二进制文件。

      【讨论】:

      • 感谢您的解释。
      【解决方案4】:

      static 关键字与函数定义一起使用时表示该函数具有文件级范围。这意味着函数名称仅在文件本身中可见。函数定义中使用的static关键字修改函数名可见性,不修改函数返回类型。

      所以声明为静态的函数可以返回任何类型的类型。

      在函数体中定义的变量上使用static 用于指示该变量将在应用程序加载和启动时创建。因此,如果您在函数内的变量上使用static 修饰符,则调用函数时不会在堆栈上创建该变量。它独立于何时调用函数而存在。但是变量的可见性只在函数内部。

      在您的示例中,您有一个函数返回 static 变量的地址。您可以这样做,但是您必须了解这种使用不是线程安全的。换句话说,所有调用该函数的线程都将在相同的内存位置获取相同的变量,而不是它们自己的变量版本。

      您还必须了解,如果您返回 static 变量的地址,也可能导致重入和递归问题。原因是堆栈上的变量提供了可重入性和递归性,因为每次调用函数时,都会向堆栈添加一个新框架,因此每个函数调用都有自己的堆栈框架,因此有自己的一组变量。

      这是标准 C 库中旧的 strtok() 函数的一个已知问题,它使用 strtok() 函数中的变量来维持调用之间的状态,使用 NULL 作为最后一次调用 @987654329 的字符串地址@ 在解析字符串时关闭。我看到了一个问题,一个名为 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
      }
      

      【讨论】:

      • 谢谢先生的详尽解释!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-01-05
      • 2011-03-10
      • 1970-01-01
      • 1970-01-01
      • 2015-03-31
      相关资源
      最近更新 更多