실행 가능한 최소 다중 파일 범위 예
여기 static
에서는 여러 파일에서 함수 정의 범위에 어떤 영향을 미치는지 설명 합니다.
ac
#include <stdio.h>
/* Undefined behavior: already defined in main.
* Binutils 2.24 gives an error and refuses to link.
* /programming/27667277/why-does-borland-compile-with-multiple-definitions-of-same-object-in-different-c
*/
/*void f() { puts("a f"); }*/
/* OK: only declared, not defined. Will use the one in main. */
void f(void);
/* OK: only visible to this file. */
static void sf() { puts("a sf"); }
void a() {
f();
sf();
}
main.c
#include <stdio.h>
void a(void);
void f() { puts("main f"); }
static void sf() { puts("main sf"); }
void m() {
f();
sf();
}
int main() {
m();
a();
return 0;
}
GitHub의 상류 .
컴파일하고 실행하십시오.
gcc -c a.c -o a.o
gcc -c main.c -o main.o
gcc -o main main.o a.o
./main
산출:
main f
main sf
main f
a sf
해석
sf
각 파일마다 하나씩 두 개의 개별 기능이 있습니다.
- 단일 공유 기능이 있습니다
f
평소와 같이 범위가 작을수록 좋습니다. 가능하면 항상 함수를 선언하십시오 static
.
C 프로그래밍에서 파일은 종종 "클래스"를 나타내는 데 사용되며 static
함수는 클래스의 "비공개"메소드를 나타냅니다.
일반적인 C 패턴은 this
구조체를 첫 번째 "메서드"인수로 전달하는 것인데, 기본적으로 C ++이 수행하는 작업입니다.
그것에 대해 말하는 표준
C99 N1256 draft 6.7.1 "스토리지 클래스 지정자"는 "스토리지 클래스 지정자"라고 말합니다 static
.
6.2.2 / 3 "식별자 링크"는 다음을 static
의미합니다 internal linkage
.
객체 또는 함수에 대한 파일 범위 식별자 선언에 스토리지 클래스 지정자 정적이 포함되어 있으면 식별자에 내부 연결이 있습니다.
그리고 6.2.2 / 2는 internal linkage
우리의 예제에서와 같이 동작 한다고 말합니다 :
전체 프로그램을 구성하는 변환 단위 및 라이브러리 세트에서 외부 링크가있는 특정 식별자의 각 선언은 동일한 객체 또는 함수를 나타냅니다. 하나의 번역 단위 내에서 내부 연결이있는 식별자의 각 선언은 동일한 객체 또는 함수를 나타냅니다.
여기서 "번역 단위"는 사전 처리 후 소스 파일입니다.
GCC가 ELF (Linux)를 위해 어떻게 구현합니까?
와 STB_LOCAL
바인딩.
우리가 컴파일하면 :
int f() { return 0; }
static int sf() { return 0; }
다음과 같이 심볼 테이블을 분해하십시오.
readelf -s main.o
출력에는 다음이 포함됩니다.
Num: Value Size Type Bind Vis Ndx Name
5: 000000000000000b 11 FUNC LOCAL DEFAULT 1 sf
9: 0000000000000000 11 FUNC GLOBAL DEFAULT 1 f
바인딩은 그들 사이의 유일한 중요한 차이점입니다. 섹션에 Value
대한 오프셋 일 뿐이 .bss
므로 차이가있을 것으로 예상합니다.
STB_LOCAL
http://www.sco.com/developers/gabi/2003-12-17/ch4.symtab.html 의 ELF 사양에 설명되어 있습니다 .
STB_LOCAL 로컬 심볼은 해당 정의를 포함하는 오브젝트 파일 외부에 표시되지 않습니다. 동일한 이름의 로컬 기호가 서로 방해하지 않고 여러 파일에 존재할 수 있습니다
표현하기에 완벽한 선택 static
입니다.
정적이없는 함수는 STB_GLOBAL
이며 사양은 다음과 같습니다.
링크 편집기가 재배치 가능한 여러 오브젝트 파일을 결합 할 때 동일한 이름을 가진 STB_GLOBAL 기호의 다중 정의를 허용하지 않습니다.
이는 여러 비 정적 정의의 링크 오류와 일치합니다.
로 최적화를 크랭크 -O3
하면 sf
심볼이 심볼 테이블에서 완전히 제거됩니다. 어쨌든 외부에서는 사용할 수 없습니다. TODO 최적화가 없을 때 심볼 테이블에 정적 함수를 유지하는 이유는 무엇입니까? 그들은 무엇이든 사용할 수 있습니까?
또한보십시오
C ++ 익명 네임 스페이스
C ++에서는 정적 대신 익명 네임 스페이스를 사용하여 비슷한 효과를 얻을 수 있지만 유형 정의를 숨 깁니다. 이름이없는 / 익명 네임 스페이스와 정적 함수