【问题标题】:What is the use of Static in declaring character arrays?Static 在声明字符数组时有什么用?
【发布时间】:2018-08-22 04:27:14
【问题描述】:

我在 C 语言的 Hackerrank 中执行此 program 并解决了程序,但没有将我的字符数组“结果”声明为静态。它返回了一个错误,我的输出与预期输出不匹配。但是只要我在数组'result'的声明中插入关键字'static',代码就运行成功了。

这是我的代码 sn-p:

char* timeConversion(char* s) 
{
    int i;
    static char result[100];      // this doesn't work if i remove the word 'static'
    if (s[0]=='1' && s[1]=='2' && s[8]=='A')
        { 
            result[0]='0';
            result[1]='0';
            for (i=2;i<8;i++)
               result[i]=s[i];  
        }
    else if (s[0]=='1' && s[1]=='2' && s[8]=='P')
        for (i=0;i<8;i++)
               result[i]=s[i];
    else
    {
       if (s[8]=='A')
           for (i=0;i<8;i++)
               result[i]=s[i];
       if (s[8]=='P')
       {
           result[0]=s[0]+1;
           result[1]=s[1]+2;
           for (i=2;i<8;i++)
               result[i]=s[i];           
       }        
     }
    return result; 
}

我不明白,这里的静态有什么用?

【问题讨论】:

  • 如果你读过你的教科书,它对局部静态变量有什么看法?
  • 静态变量存在于程序的整个生命周期中,它在函数调用之间保存它的值,局部变量仅在函数工作期间存在。这就是为什么当你删除关键字静态时它不起作用,你返回局部变量。另外请阅读静态它在某些情况下具有另一种含义,对于函数或全局范围变量

标签: c arrays static character


【解决方案1】:

两件事:

  1. 您正在从您的函数返回堆栈分配数组的地址。如果不是static,那么您只会返回一个不再存在的数组的地址,因为通常堆栈上的对象会在超出范围时消失(即函数返回时)。要从调用代码实际可以使用的函数返回数组,它必须在堆上分配(即使用malloc)或声明为static,因为使用@ 声明的函数中的局部变量987654324@ 限定符在函数返回后仍然存在。

  2. 如果没有static 限定符的变量被声明但没有显式初始化,它只会获取当时已经在内存中的任何内容。

    如果使用 static 限定符声明局部变量或数组,则它会隐式初始化为零。这意味着变量result 可以填充解析的日期/时间值,并保证是一个以空值结尾的字符串,因为函数中的代码未填充的所有数组元素都已经为零。

【讨论】:

  • 请注意,OP 也返回了这个变量,这对于非静态局部变量是非法的。
  • @r3musn0x 感谢您指出这一点。我通过用puts(result) 替换return 语句简化了在我的机器上调试OP 的代码,所以我忽略了这一点。
  • 好的。因此,如果不使用“静态”这个词,那么当我从函数返回时,数组就会超出范围,即 main() 找不到任何具有我刚刚返回的地址的数组。但是如果我使用“静态”这个词,那么即使在命令返回到 main() 之后,数组也会保留在内存中,因此 main() 可以访问数组。是这样吗?
  • @RajdeepDutta 差不多。
【解决方案2】:

C11 6.2.2 标识符的链接(P3):

如果声明一个对象的文件范围标识符或 函数包含存储类说明符static,标识符 有内部联系。30)

脚注:

30) 函数声明可以包含存储类说明符 static 仅在文件范围内;看 6.7.1.

这意味着static变量被声明一次,它的生命周期是程序的整个执行。这就是为什么返回静态数组在您的代码中工作正常,这是有道理的。

如果您删除 static 关键字,则数组变为本地或自动,并且局部变量的范围仅存在于声明它的块或函数中。在您的代码中,您试图返回本地数组,它被调用undefined behaviour.

GCC 编译器警告:

In function 'timeConversion':
prog.c:30:12: warning: function returns address of local variable [-Wreturn-local-addr]
     return result;
            ^~~~~~

【讨论】:

    【解决方案3】:

    我不明白,这里的静态有什么用?

    与您的程序相关的static 的几个含义,取自C99 标准(N1256):

    6.2.4 对象的存储时长

    1. 对象具有决定其生命周期的存储持续时间。共有三个存储 持续时间:静态、自动和分配。分配的存储在 7.20.3 中描述。

    2. 对象的生命周期是程序执行的一部分,在此期间存储是 保证为它保留。一个对象存在,有一个常量地址,25) 并保留 它在其整个生命周期中的最后存储值。26) 如果一个对象在其生命周期之外被引用,则该行为是未定义的。当指针的值变得不确定时 它指向的对象到达其生命周期的尽头。

    3. 一个对象,其标识符用外部或内部链接声明,或用 存储类说明符 static 具有静态存储持续时间。它的生命周期是整个 程序的执行及其存储的值仅在程序之前初始化一次 启动。

    6.7.8 初始化
    ....
    10.如果一个具有自动存储持续时间的对象没有被显式初始化,它的值是不确定的。 如果一个具有静态存储时长的对象没有被显式初始化,那么:

    ——如果是指针类型,则初始化为空指针;
    如果是算术类型,则初始化为(正或无符号)零;
    如果是聚合,则每个成员都根据这些规则(递归)进行初始化;
    — 如果它是一个联合,则第一个命名的成员根据这些被初始化(递归) 规则。

    因此,在您的示例中,static 指定了 result 数组的生命周期,并根据上面突出显示的规则初始化数组。

    【讨论】:

      猜你喜欢
      • 2011-06-08
      • 2016-02-04
      • 1970-01-01
      • 2020-03-03
      • 2011-10-02
      • 1970-01-01
      • 1970-01-01
      • 2012-10-22
      • 2014-06-26
      相关资源
      最近更新 更多