关于语法:”static”在C中是什么意思?

What does “static” mean in C?

我在C代码的不同地方看到过static这个词;这是否像C中的静态函数/类(实现是跨对象共享的)?


  • 函数内部的静态变量在调用之间保持其值。
  • 静态全局变量或函数仅在其声明的文件中"可见"
  • (1)如果你是新手的话,是比较陌生的话题,下面是一个例子:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    #include <stdio.h>

    void foo()
    {
        int a = 10;
        static int sa = 10;

        a += 5;
        sa += 5;

        printf("a = %d, sa = %d
    "
    , a, sa);
    }


    int main()
    {
        int i;

        for (i = 0; i < 10; ++i)
            foo();
    }

    印刷品:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    a = 15, sa = 15
    a = 15, sa = 20
    a = 15, sa = 25
    a = 15, sa = 30
    a = 15, sa = 35
    a = 15, sa = 40
    a = 15, sa = 45
    a = 15, sa = 50
    a = 15, sa = 55
    a = 15, sa = 60

    这对于函数需要在调用之间保持某种状态,并且不想使用全局变量的情况非常有用。但是要小心,这个特性应该非常谨慎地使用——它会使您的代码不安全,更难理解。

    (2)被广泛用作"访问控制"功能。如果您有一个实现某些功能的.c文件,它通常只向用户公开一些"公共"功能。它的其余功能应该是static,这样用户就不能访问它们。这是封装,一个好的实践。

    引用维基百科:

    In the C programming language, static
    is used with global variables and
    functions to set their scope to the
    containing file. In local variables,
    static is used to store the variable
    in the statically allocated memory
    instead of the automatically allocated
    memory. While the language does not
    dictate the implementation of either
    type of memory, statically allocated
    memory is typically reserved in data
    segment of the program at compile
    time, while the automatically
    allocated memory is normally
    implemented as a transient call stack.

    有关详细信息,请参阅此处和此处。

    为了回答你的第二个问题,这不像C。

    然而,在C++中,EDCOX1(0)也用于定义类属性(在同一类的所有对象之间共享)和方法。在C中没有类,所以这个特性是不相关的。


    有一个使用在需要覆盖的一部分,这是在为数组类型声明为一个函数的参数:

    1
    2
    3
    4
    int someFunction(char arg[static 10])
    {
        ...
    }

    在这上下文,这是传递到该函数的参数应该提醒char阵列的类型必须与至少10的元素,在它。更多信息在这里湖我的问题。


    简短回答…这要看情况而定。

  • 静态定义的局部变量在函数调用之间不会丢失其值。换句话说,它们是全局变量,但作用域是它们在中定义的局部函数。

  • 静态全局变量在定义它们的C文件之外不可见。

  • 静态函数在定义它们的C文件之外不可见。


  • 多变量范围的例子文件

    在一个静态的知识范围,说明在多功能定义文件)。

    交流

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    #include <stdio.h>

    /*
    Undefined behavior: already defined in main.
    Binutils 2.24 gives an error and refuses to link.
    https://stackoverflow.com/questions/27667277/why-does-borland-compile-with-multiple-definitions-of-same-object-in-different-c
    */

    /*int i = 0;*/

    /* Works in GCC as an extension: https://stackoverflow.com/a/3692486/895245 */
    /*int i;*/

    /* OK: extern. Will use the one in main. */
    extern int i;

    /* OK: only visible to this file. */
    static int si = 0;

    void a() {
        i++;
        si++;
        puts("a()");
        printf("i = %d
    "
    , i);
        printf("si = %d
    "
    , si);
        puts("");
    }

    main.c

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    #include <stdio.h>

    int i = 0;
    static int si = 0;

    void a();    

    void m() {
        i++;
        si++;
        puts("m()");
        printf("i = %d
    "
    , i);
        printf("si = %d
    "
    , si);
        puts("");
    }

    int main() {
        m();
        m();
        a();
        a();
        return 0;
    }

    GitHub的上游。

    编译和运行:

    1
    2
    3
    gcc -c a.c -o a.o
    gcc -c main.c -o main.o
    gcc -o main main.o a.o

    输出:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    m()
    i = 1
    si = 1

    m()
    i = 2
    si = 2

    a()
    i = 3
    si = 1

    a()
    i = 4
    si = 2

    解读

    • 有两个独立的变量和一个si,每个文件
    • 有一个单一的共享变量的i

    照常的,更小的范围,这是更好的,如果你能static声明变量。

    在C编程,文件是经常用来代表"班",static私有静态成员变量和方法的类。

    说它是什么标准

    C99 n1256选秀6.7.1项存储类说明符"说,"这是一个staticspecifier存储舱。

    6.2.2/3"键):staticimplies internal linkage说标识符"

    If the declaration of a file scope identifier for an object or a function contains the storage-class specifier static, the identifier has internal linkage.

    6.2.2 / 2和说,在我们的例子internal linkagebehaves样:

    In the set of translation units and libraries that constitutes an entire program, each declaration of a particular identifier with external linkage denotes the same object or function. Within one translation unit, each declaration of an identifier with internal linkage denotes the same object or function.

    在"翻译单位是一个源文件预处理后。

    如何实现它的GCC 11(Linux)?

    STB_LOCAL结合。

    如果我们编译:

    1
    2
    int i = 0;
    static int si = 0;

    一个符号表和拆卸:

    1
    readelf -s main.o

    输出包含:

    1
    2
    3
    Num:    Value          Size Type    Bind   Vis      Ndx Name
      5: 0000000000000004     4 OBJECT  LOCAL  DEFAULT    4 si
     10: 0000000000000000     4 OBJECT  GLOBAL DEFAULT    4 i

    因此,之间的差异是唯一显着的结合。只是他们的Value偏移到.bss截面,所以我们希望它显示。

    STB_LOCAL是记录在11个规格在http:/ / / /开发者www.sco.com加比2003年12 ch4.symtab.html:17号

    STB_LOCAL Local symbols are not visible outside the object file containing their definition. Local symbols of the same name may exist in multiple files without interfering with each other

    这使得它一个完美的选择static代表。

    没有静态变量是STB_GLOBAL和规格,说:

    When the link editor combines several relocatable object files, it does not allow multiple definitions of STB_GLOBAL symbols with the same name.

    这是一致的与非静态定义在多链路错误。

    如果我们有-O3曲柄上的优化,si符号从符号表被删除,它是不能使用以外的不管怎样。为什么要做静态变量的符号表,当没有在所有的优化?他们可以被用于什么?我们的调试。

    因此,湖

    • 类似的static函数:http:/ / / / 30319812 895245 stackoverflow.com
    • 一个比较staticextern",这是相反的:我如何使用外部变量之间分享的源文件?

    C + +的匿名命名空间

    在C + +,你可能想使用匿名命名空间,而不是静态的,这achieves类似的效应,但继续隐藏匿名命名空间中的类型定义:unnamed /静态函数。


    这取决于:

    1
    2
    3
    4
    5
    int foo()
    {
       static int x;
       return ++x;
    }

    函数将返回1、2、3等---变量不在堆栈上。

    答:

    1
    2
    3
    static int foo()
    {
    }

    这意味着这个函数只在这个文件中有作用域。所以A.C和B.C可以有不同的foo(),而foo不暴露于共享对象。因此,如果您在a.c中定义了foo,则无法从b.c或任何其他地方访问它。

    在大多数C库中,所有"私有"功能都是静态的,而大多数"公共"功能则不是。


    人们一直说C中的"静态"有两个含义。我提供了另一种查看它的方式,赋予它一个单一的含义:

    • 将"static"应用于项会强制该项具有两个属性:(a)在当前范围之外不可见;(b)它是持久的。

    它似乎有两个含义的原因是,在C语言中,可能应用"static"的每个项都已经具有这两个属性中的一个,因此似乎该特定用法只涉及另一个属性。

    例如,考虑变量。在函数外部声明的变量已经具有持久性(在数据段中),因此应用"static"只能使它们在当前范围(编译单元)之外不可见。相反,函数内部声明的变量在当前范围(函数)之外已经不可见,因此应用"static"只能使它们持久化。

    将"static"应用于函数就像将其应用于全局变量一样-代码必须是持久的(至少在语言中),因此只能更改可见性。

    注意:这些注释只适用于C++中的C.,将"static"应用到类方法中确实赋予了关键字不同的含义。类似于c99数组参数扩展。


    static在不同的上下文中表示不同的事物。

  • 可以在C函数中声明静态变量。此变量仅在函数中可见,但其行为类似于全局变量,因为它只初始化一次并保留其值。在本例中,每次调用foo()时,它都会打印一个递增的数字。静态变量只初始化一次。

    1
    2
    3
    4
    5
    void foo ()
    {
    static int i = 0;
    printf("%d", i); i++
    }
  • 静态的另一种用法是在.c文件中实现函数或全局变量,但不希望其符号在文件生成的.obj之外可见。例如

    1
    static void foo() { ... }

  • 维基百科:

    In the C programming language, static is used with global variables and functions to set their scope to the containing file. In local variables, static is used to store the variable in the statically allocated memory instead of the automatically allocated memory. While the language does not dictate the implementation of either type of memory, statically allocated memory is typically reserved in data segment of the program at compile time, while the automatically allocated memory is normally implemented as a transient call stack.


    我不喜欢回答一个老问题,但我认为没有人在"C编程语言"的A4.1节中提到K&R是如何解释这个问题的。

    简而言之,静态一词有两种含义:

  • 静态是两个存储类之一(另一个是自动)。静态对象在调用之间保持其值。在所有块之外声明的对象始终是静态的,不能使其成为自动的。
  • 但是,当static关键字(重点强调它在代码作为关键字)与声明一起使用,它提供对象内部链接,因此只能在该翻译单元内使用。但是,如果在函数中使用关键字,它将更改对象的存储类(对象将只在该函数中可见)。与static相反的是extern关键字,它提供对象外部链接。
  • Peter van der Linden在"专家C编程"中给出了这两个含义:

    • 在函数内部,在调用之间保留其值。
    • 在函数级别,仅在此文件中可见。


    在C语言中,static有两个含义,这取决于它的使用范围。在全局范围中,当在文件级别声明对象时,意味着该对象仅在该文件中可见。

    在任何其他范围中,它声明一个对象,该对象将在输入特定范围的不同时间之间保留其值。例如,如果一个int在一个过程中被删除:

    1
    2
    3
    4
    5
    6
    void procedure(void)
    {
       static int i = 0;

       i++;
    }

    第一次调用过程时,"i"的值初始化为零,并且每次调用过程时都保留该值。如果打印"i",它将输出一个0、1、2、3……的序列。


    如果您在函数static中声明一个变量,它的值将不会存储在函数调用堆栈中,并且在您再次调用函数时仍然可用。

    如果您声明一个全局变量static,它的作用域将被限制在您声明它的文件中。这比在整个程序中都可以读取和修改的常规全局设置稍安全。


    如果你在一mytest.c声明本文件:

    1
    static int my_variable;

    那么这个变量只能在本文件的湖泊。出口的变量不能被其他任何地方。

    如果你在一个函数声明的变量的值要保持其价值的每一次函数是所谓的。

    a static函数不能在美国以外的文件。在A *。这样你的文件隐藏,如果你声明变量和函数是静态的。


    C中的静态变量具有程序的生存期。

    如果在函数中定义,则它们具有本地作用域,即只能在这些函数中访问它们。静态变量的值在函数调用之间保留。

    例如:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    void function()
    {
        static int var = 1;
        var++;
        printf("%d", var);
    }

    int main()
    {
        function(); // Call 1
        function(); // Call 2
    }

    在上述程序中,var存储在数据段中。它的生命周期是整个C程序。

    函数调用1后,var变为2。函数调用2后,var变为3。

    函数调用之间的var值不会被破坏。

    如果var介于非静态变量和局部变量之间,它将存储在C程序的堆栈段中。由于函数的堆栈帧在函数返回后被破坏,因此EDOCX1的值(0)也被破坏。

    初始化的静态变量存储在C程序的数据段中,而未初始化的静态变量存储在BSS段中。

    关于静态的另一个信息:如果一个变量是全局的和静态的,那么它有C程序的生命周期,但是它有文件范围。它只在该文件中可见。

    尝试一下:

    文件1.C

    1
    2
    3
    4
    5
    6
    static int x;

    int main()
    {
        printf("Accessing in same file%d", x):
    }

    文件2.C

    1
    2
    3
    4
    5
    6
    7
    8
    9
        extern int x;
        func()
        {
            printf("accessing in different file %d",x); // Not allowed, x has the file scope of file1.c
        }

    run gcc -c file1.c

    gcc -c file2.c

    现在尝试使用以下链接:

    1
    gcc -o output file1.o file2.o

    它将给出一个链接器错误,因为x的文件范围为file1.c,并且链接器将无法解析对file2.c中使用的变量x的引用。

    参考文献:

  • http://en.wikipedia.org/wiki/translation_Unit_u(编程)
  • http://en.wikipedia.org/wiki/call_堆栈

  • 它是最新的静态变量在函数得到注意到在第一个输入initialized售后呼叫功能和持续甚至在已经完成的案例;递归函数中的静态变量,那么initialized只读一次。也可在persists和递归调用的呼叫后,即使已经完成的功能。

    如果外部变量已创建的函数,它只是意味着程序员可以使用变量的源文件已被变量。


    静态变量是您可以在函数中使用的特殊变量,它保存调用之间的数据,并且不会在调用之间删除数据。例如:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    void func(){
        static int count; // If you don't declare its value, the value automatically initializes to zero
        printf("%d,", count);
        count++;
    }

    void main(){
        while(true){
            func();
        }
    }

    输出:

    0,1,2,3,4,5,…


    一个静态变量值之间的函数调用persists andits范围是有限的本地块一个静止无功initializes值总是0


    有两种情况:

    (1)声明static的局部变量:分配在数据段而不是堆栈中。它的值在您再次调用函数时保持不变。

    (2)全局变量或声明为static的函数:编译单元外部不可见(即链接时符号表中的局部符号)。


    在C语言编程中,static是一个保留关键字,它控制生存期和可见性。如果我们在一个函数中将一个变量声明为静态变量,那么它将只在整个函数中可见。在这种用法中,静态变量的生存期将在函数调用时开始,并在函数执行后销毁。您可以看到以下示例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    #include<stdio.h>
    int counterFunction()
    {
      static int count = 0;
      count++;
      return count;
    }

    int main()
    {
      printf("First Counter Output = %d
    "
    , counterFunction());
      printf("Second Counter Output = %d", counterFunction());
      return 0;
    }

    上面的程序将给出这个输出:第一计数器输出=1第二计数器输出=1因为一旦调用函数,它将初始化count=0。当我们执行counterfunction时,它会破坏count变量。