Programming

C의 정적 함수

procodes 2020. 5. 26. 21:23
반응형

C의 정적 함수


C에서 함수를 정적으로 만드는 요점은 무엇입니까?


함수를 만들면 static다른 번역 단위에서 숨겨져 캡슐화를 제공하는 데 도움이됩니다 .

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

pmg 은 캡슐화에 대해 자리 잡고있다; 함수를 다른 변환 단위 (또는 그로 인해 ) 에서 숨기는 것 외에도 함수를 만들면 static컴파일러 최적화가있을 때 성능 이점을 얻을 수 있습니다.

static코드가 주소에 대한 포인터를 사용하지 않는 한 현재 변환 단위 외부 에서는 함수를 호출 할 수 없으므로 컴파일러는 모든 호출 지점을 제어합니다.

즉, 비표준 ABI를 자유롭게 사용하거나 완전히 인라인하거나 외부 연결 기능으로는 불가능한 다른 최적화를 수행 할 수 있습니다.


staticC 키워드는 함수가 해당 파일에만 존재하도록 컴파일 된 파일 (.h와 반대로 .c)에서 사용됩니다.

일반적으로 함수를 만들 때 컴파일러는 링커가 함수 호출을 해당 함수에 연결하는 데 사용할 수있는 cruft를 생성합니다. static 키워드를 사용하면 링커에 의존하지 않고 수행 할 수 있기 때문에 동일한 파일 내의 다른 함수가이 함수를 호출 할 수 있지만 링커에는 다른 파일이 함수에 액세스하도록하는 정보가 없습니다.


위의 게시물을 보면 한 가지 세부 사항을 지적하고 싶습니다.

기본 파일 ( "main.c")이 다음과 같다고 가정합니다.

#include "header.h"

int main(void) {
    FunctionInHeader();
}

이제 세 가지 경우를 고려하십시오.

  • 사례 1 : 헤더 파일 ( "header.h")은 다음과 같습니다.

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

    그런 다음 Linux에서 다음 명령을 수행하십시오.

    gcc main.c header.h -o main
    

    성공할 것이다 ! 다음 중 하나를 실행하면

    ./main
    

    출력은

    헤더 내부의 함수 호출

    정적 함수가 인쇄해야하는 것은 다음과 같습니다.

  • 사례 2 : 헤더 파일 ( "header.h")은 다음과 같습니다.

    static void FunctionInHeader();     
    

    또한 "header.c"파일이 하나 더 있습니다.

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

    그런 다음 다음 명령

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

    오류가 발생합니다.

  • 사례 3 :

    헤더 파일 ( "header.h")이 다음을 제외하고 사례 2와 유사합니다.

    void FunctionInHeader(); // keyword static removed
    

    그런 다음 2와 같은 명령이 성공하고 ./main을 추가로 실행하면 예상 결과가 나타납니다.

따라서이 테스트 (Acer x86 컴퓨터, Ubuntu OS에서 실행)에서 나는

static 키워드는 함수가 선언 된 곳이 아닌 다른 파일에 함수가 정의되지 않도록합니다.

내가 틀렸다면 정정 해주세요.


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.


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.

참고URL : https://stackoverflow.com/questions/5319361/static-function-in-c

반응형