static
C 코드의 다른 곳에서 사용되는 단어를 보았습니다 . 이것은 C #의 정적 함수 / 클래스와 비슷합니까 (구현이 객체간에 공유되는 경우)?
답변
- 함수 내부의 정적 변수는 호출간에 값을 유지합니다.
- 정적 전역 변수 또는 함수는 선언 된 파일에서만 “본”
초보자라면 (1)이 더 많은 주제입니다.
#include <stdio.h>
void foo()
{
int a = 10;
static int sa = 10;
a += 5;
sa += 5;
printf("a = %d, sa = %d\n", a, sa);
}
int main()
{
int i;
for (i = 0; i < 10; ++i)
foo();
}
인쇄합니다 :
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
사용자가 액세스 할 수 없도록 나머지 기능을 수행해야 합니다. 이것은 캡슐화, 좋은 습관입니다.
인용 위키 백과 :
C 프로그래밍 언어에서 static은 전역 변수 및 함수와 함께 사용되어 해당 범위를 포함 파일로 설정합니다. 로컬 변수에서 static은 자동 할당 된 메모리 대신 정적 할당 된 메모리에 변수를 저장하는 데 사용됩니다. 언어가 두 가지 유형의 메모리 구현을 지시하지는 않지만 정적으로 할당 된 메모리는 일반적으로 컴파일 타임에 프로그램의 데이터 세그먼트에 예약되며 자동 할당 된 메모리는 일반적으로 임시 호출 스택으로 구현됩니다.
그리고 두 번째 질문에 대답하기 위해 C #과 다릅니다.
그러나 C ++에서는 static
클래스 속성 (같은 클래스의 모든 객체간에 공유) 및 메소드를 정의하는 데에도 사용됩니다. C에는 클래스가 없으므로이 기능은 관련이 없습니다.
답변
여기에서 다루지 않은 용도가 하나 더 있으며, 이는 함수에 대한 인수로 배열 유형 선언의 일부입니다.
int someFunction(char arg[static 10])
{
...
}
이와 관련하여이 함수에 전달 된 인수는 char
10 개 이상의 요소가 포함 된 유형의 배열이어야 함을 지정 합니다. 자세한 내용은 내 질문을 참조하십시오 여기 하십시오 .
답변
짧은 대답 … 그것은 달려 있습니다.
-
정적 정의 로컬 변수는 함수 호출간에 값을 잃지 않습니다. 다시 말해, 그것들은 전역 변수이지만 그것들이 정의 된 지역 함수의 범위를 갖습니다.
-
정적 전역 변수는 정의 된 C 파일 외부에서 볼 수 없습니다.
-
정적 함수는 정의 된 C 파일 외부에서 볼 수 없습니다.
답변
다중 파일 변수 범위 예
여기서 정적이 여러 파일에서 함수 정의 범위에 미치는 영향을 설명합니다.
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
*/
/*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\n", i);
printf("si = %d\n", si);
puts("");
}
main.c
#include <stdio.h>
int i = 0;
static int si = 0;
void a();
void m() {
i++;
si++;
puts("m()");
printf("i = %d\n", i);
printf("si = %d\n", si);
puts("");
}
int main() {
m();
m();
a();
a();
return 0;
}
컴파일하고 실행하십시오.
gcc -c a.c -o a.o
gcc -c main.c -o main.o
gcc -o main main.o a.o
산출:
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 draft 6.7.1 “스토리지 클래스 지정자”는 “스토리지 클래스 지정자”라고 말합니다 static
.
6.2.2 / 3 “식별자의 연결”은 다음을 static
의미합니다 internal linkage
.
객체 또는 함수에 대한 파일 범위 식별자 선언에 스토리지 클래스 지정자 정적이 포함되어 있으면 식별자에 내부 연결이 있습니다.
그리고 6.2.2 / 2는 internal linkage
우리 예제에서와 같이 동작 한다고 말합니다 :
전체 프로그램을 구성하는 변환 단위 및 라이브러리 세트에서 외부 링크가있는 특정 식별자의 각 선언은 동일한 객체 또는 함수를 나타냅니다. 하나의 변환 단위 내에서 내부 연결이있는 식별자의 각 선언은 동일한 객체 또는 함수를 나타냅니다.
여기서 “번역 단위는 전처리 후 소스 파일입니다.
GCC가 ELF (Linux)를 위해 어떻게 구현합니까?
와 더불어 STB_LOCAL
바인딩.
우리가 컴파일하면 :
int i = 0;
static int si = 0;
다음과 같이 심볼 테이블을 분해하십시오.
readelf -s main.o
출력에는 다음이 포함됩니다.
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
http://www.sco.com/developers/gabi/2003-12-17/ch4.symtab.html 의 ELF 사양에 설명되어 있습니다 .
STB_LOCAL 로컬 심볼은 해당 정의를 포함하는 오브젝트 파일 외부에 표시되지 않습니다. 동일한 이름의 로컬 기호가 서로 방해하지 않고 여러 파일에 존재할 수 있습니다
표현하기에 완벽한 선택 static
입니다.
정적 변수가없는 변수 STB_GLOBAL
는 사양이며 다음과 같이 말합니다.
링크 편집기가 재배치 가능한 여러 오브젝트 파일을 결합 할 때 동일한 이름을 가진 STB_GLOBAL 기호의 다중 정의를 허용하지 않습니다.
이는 여러 비 정적 정의의 링크 오류와 일치합니다.
로 최적화를 크랭크 -O3
하면 si
심볼이 심볼 테이블에서 완전히 제거됩니다. 어쨌든 외부에서는 사용할 수 없습니다. TODO 최적화가 없을 때 왜 심볼 테이블에 정적 변수를 유지합니까? 그들은 무엇이든 사용할 수 있습니까? 아마도 디버깅을 위해.
또한보십시오
static
기능 과 유사 함 : https://stackoverflow.com/a/30319812/895245- 비교
static
에extern
“반대”않는, 어떻게 소스 파일 간의 공유 변수에 통근 사용합니까?
C ++ 익명 네임 스페이스
C ++에서는 정적 대신 익명 네임 스페이스를 사용하여 비슷한 효과를 얻을 수 있지만 유형 정의를 숨 깁니다. 이름이없는 / 익명 네임 스페이스와 정적 함수
답변
때에 따라 다르지:
int foo()
{
static int x;
return ++x;
}
이 함수는 1, 2, 3 등을 반환합니다. — 변수가 스택에 없습니다.
ac :
static int foo()
{
}
이 함수는이 파일에서만 범위를 갖습니다. 따라서 ac와 bc는 서로 다른 foo()
s를 가질 수 있으며 foo는 공유 객체에 노출되지 않습니다. 따라서 AC에서 foo를 정의 b.c
하면 다른 곳 에서 또는 다른 곳에서 액세스 할 수 없습니다 .
대부분의 C 라이브러리에서 모든 “비공개”기능은 정적이며 대부분의 “공용”기능은 아닙니다.
답변
사람들은 C에서 ‘정적’은 두 가지 의미가 있다고 계속 말합니다. 나는 그것을 의미하는 대체 방법을 제공합니다.
- 항목에 ‘정적’을 적용하면 해당 항목에 다음 두 가지 속성이 있습니다. (b) 영구적이다.
그것이 두 가지 의미를 갖는 것처럼 보이는 이유는 C에서 ‘정적’이 적용될 수있는 모든 항목이 이미이 두 가지 속성 중 하나를 가지고 있기 때문에 특정 용도가 다른 것만 포함하는 것처럼 보입니다 .
예를 들어 변수를 고려하십시오. 함수 외부에서 선언 된 변수는 이미 데이터 세그먼트에서 지속성을 가지고 있으므로 ‘정적’을 적용하면 현재 범위 (컴파일 단위) 외부에서만 보이지 않습니다. 반대로, 함수 내부에 선언 된 변수는 이미 현재 범위 (함수) 외부에 표시되지 않으므로 ‘정적’을 적용하면 지속될 수 있습니다.
함수에 ‘정적’을 적용하는 것은 전역 변수에 적용하는 것과 같습니다. 코드는 반드시 영구적이어야합니다 (적어도 언어 내에서). 따라서 가시성 만 변경할 수 있습니다.
참고 :이 주석은 C에만 적용됩니다. C ++에서 클래스 메소드에 ‘정적’을 적용하면 키워드에 다른 의미가 부여됩니다. C99 배열 인수 확장의 경우와 유사합니다.
답변
Wikipedia에서 :
C 프로그래밍 언어에서 static 은 전역 변수 및 함수와 함께 사용되어 해당 범위를 포함 파일로 설정합니다. 로컬 변수에서 static은 자동 할당 된 메모리 대신 정적 할당 된 메모리에 변수를 저장하는 데 사용됩니다. 언어가 두 가지 유형의 메모리 구현을 지시하지는 않지만 정적으로 할당 된 메모리는 일반적으로 컴파일 타임에 프로그램의 데이터 세그먼트에 예약되며 자동 할당 된 메모리는 일반적으로 임시 호출 스택으로 구현됩니다.