static function in C

2020-01-27 09:06发布

问题:

What is the point of making a function static in C?

回答1:

Making a function static hides it from other translation units, which helps provide encapsulation.

helper_file.c

int f1(int);        /* prototype */
static int f2(int); /* prototype */

int f1(int foo) {
    return f2(foo); /* ok, f2 is in the same translation unit */
                    /* (basically same .c file) as f1         */
}

int f2(int foo) {
    return 42 + foo;
}

main.c:

int f1(int); /* prototype */
int f2(int); /* prototype */

int main(void) {
    f1(10); /* ok, f1 is visible to the linker */
    f2(12); /* nope, f2 is not visible to the linker */
    return 0;
}


回答2:

pmg is spot on about encapsulation; beyond hiding the function from other translation units (or rather, because of it), making functions static can also confer performance benefits in the presence of compiler optimizations.

Because a static function cannot be called from anywhere outside of the current translation unit (unless the code takes a pointer to its address), the compiler controls all the call points into it.

This means that it is free to use a non-standard ABI, inline it entirely, or perform any number of other optimizations that might not be possible for a function with external linkage.



回答3:

The static keyword in C is used in a compiled file (.c as opposed to .h) so that the function exists only in that file.

Normally, when you create a function, the compiler generates cruft the linker can use to, well, link a function call to that function. If you use the static keyword, other functions within the same file can call this function (because it can be done without resorting to the linker), while the linker has no information letting other files access the function.



回答4:

Looking at the posts above I would like to point one detail.

Suppose our main file ("main.c") looks like this:

#include "header.h"

int main(void) {
    FunctionInHeader();
}

Now consider three cases:

  • Case 1: Our header file ("header.h") looks like this:

    #include <stdio.h>
    
    static void FunctionInHeader();
    
    void FunctionInHeader() {
        printf("Calling function inside header\n");
    }
    

    Then the following command on linux:

    gcc main.c header.h -o main
    

    will succeed! Following that if one runs

    ./main
    

    The output will be

    Calling function inside header

    Which is what that static function should print.

  • Case 2: Our header file ("header.h") looks like this:

    static void FunctionInHeader();     
    

    and we also have one more file "header.c", which looks like this:

    #include <stdio.h>
    
    #include "header.h"
    
    void FunctionInHeader() {
        printf("Calling function inside header\n");
    }
    

    Then the following command

    gcc main.c header.h header.c -o main
    

    will give an error.

  • Case 3:

    Similar to case 2, except that now our header file ("header.h") is:

    void FunctionInHeader(); // keyword static removed
    

    Then the same command as in case 2 will succeed, and further executing ./main will give the expected result.

So from these tests (executed on Acer x86 machine, Ubuntu OS) I made an assumption that

static keyword prevents function to be defined in another file than where it is declared.

Correct me if I am wrong.



回答5:

C programmers use the static attribute to hide variable and function declarations inside modules, much as you would use public and private declarations in Java and C++. C source files play the role of modules. Any global variable or function declared with the static attribute is private to that module. Similarly, any global variable or function declared without the static attribute is public and can be accessed by any other module. It is good programming practice to protect your variables and functions with the static attribute wherever possible.



回答6:

pmg's answer is very convincing. If you would like to know how static declarations work at object level then this below info could be interesting to you. I reused the same program written by pmg and compiler it into a .so(shared object) file

Following contents are after dumping the .so file into something human readable

0000000000000675 f1: address of f1 function

000000000000068c f2: address of f2(staticc) function

note the difference in the function address , it means something . For a function that's declared with different address , it can very well signify that f2 lives very far away or in a different segment of the object file.

Linkers use something called PLT(Procedure linkage table) and GOT(Global offsets table) to understand symbols that they have access to link to .

For now think that GOT and PLT magically bind all the addresses and a dynamic section holds information of all these functions that are visible by linker.

After dumping the dynamic section of the .so file we get a bunch of entries but only interested in f1 and f2 function.

The dynamic section holds entry only for f1 function at address 0000000000000675 and not for f2 !

Num: Value Size Type Bind Vis Ndx Name

 9: 0000000000000675    23 FUNC    GLOBAL DEFAULT   11 f1

And thats it !. From this its clear that the linker will be unsuccessful in finding the f2 function since its not in the dynamic section of the .so file.



标签: c static