programing

C에서 "정적"은 무엇을 의미하는가?

prostudy 2022. 5. 22. 11:22
반응형

C에서 "정적"은 무엇을 의미하는가?

나는 그 단어를 보았다.staticC 코드의 다른 위치에서 사용됨; 이것은 C#의 정적 함수/클래스(개체 간에 구현이 공유되는 위치)와 같은가?

  1. 함수 내부의 정적 변수는 호출 사이의 값을 유지한다.
  2. 정적 전역 변수 또는 함수가 선언된 파일에만 "표시됨"

(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개의 요소가 들어있어.자세한 내용은 여기에서 내 질문을 참조하십시오.

단답형...그것은 다르다.

  1. 정적 정의 로컬 변수는 함수 호출 사이의 값을 잃지 않는다.다시 말해, 그것들은 글로벌 변수지만, 그들이 정의한 로컬 함수에 따라 범위가 정해진다.

  2. 정적 전역 변수는 정의된 C 파일 외부에 표시되지 않는다.

  3. 정적 함수는 정의된 C 파일 외부에 표시되지 않는다.

다중 파일 변수 범위 예제

여기서는 정적이 여러 파일에 걸쳐 기능 정의 범위에 어떻게 영향을 미치는지 설명한다.

a.c.

#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\n", i);
    printf("si = %d\n", si);
    puts("");
}

본시

#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 프로그래밍에서 파일은 종종 "classes"를 나타내기 위해 사용된다.static변수는 클래스의 개인 정적 멤버를 나타낸다.

표준에 따르면

C99 N1256 초안 6.7.1 "스토리지 클래스 지정자"는 다음과 같이 말한다.static"스토리지 클래스 지정자" 입니다.

6.2.2/3 "식별자 링크"는 다음과 같다.static함축적으로 말하다internal linkage:

개체 또는 함수에 대한 파일 범위 식별자 선언에 스토리지 클래스 지정자 정적이 포함된 경우 식별자는 내부 연결을 가진다.

그리고 6.2.2/2는 다음과 같이 말한다.internal linkage우리의 예와 같이 행동한다.

전체 프로그램을 구성하는 번역 단위와 라이브러리의 집합에서, 외부 연결을 가진 특정 식별자의 각 선언은 동일한 객체나 기능을 나타낸다.하나의 번역 단위 내에서 내부 연계가 있는 식별자의 각 선언은 동일한 객체나 함수를 나타낸다.

여기서 "사전 처리 후"단위는 원본 파일이다.

GCC가 ELF(리눅스)를 위해 어떻게 구현하는가?

더 위드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_LOCALhttp://www.sco.com/developers/gabi/2003-12-17/ch4.symtab.html의 ELF 사양에 설명되어 있다.

STB_LOCAL Local 기호는 정의를 포함하는 개체 파일 외부에 표시되지 않는다.동일한 이름의 로컬 기호가 서로 간섭하지 않고 여러 파일에 존재할 수 있음

한국 로는 이다.static.

정적 변수가 없는 변수:STB_GLOBAL, 그리고 사양에는 다음과 같이 적혀 있다.

링크 편집기가 여러 개의 다시 연결 가능한 개체 파일을 결합할 때 동일한 이름의 STB_GLOBAL 기호에 대한 다중 정의를 허용하지 않는다.

복수의 비 정적 정의에 대한 링크 오류와 일관성이 있다.

다음과 같이 최적화를 크랭킹하면-O3si기호는 기호 테이블에서 완전히 제거된다. 기기는 사투리 수치다. 를 기호 않는가TODO 최적화가 없는데 왜 정적 변수를 기호 테이블 위에 유지하는가?그것들은 어떤 용도로도 사용될 수 있을까?디버깅을 위해.

참고 항목

C++ 익명 네임스페이스

C++에서는 유사한 효과를 얻지만 유형 정의를 추가로 숨기는 정적 대신 익명 네임스페이스를 사용할 수 있다.이름 없는/익명된 네임스페이스 대 정적 함수

static다른 맥락에서 다른 것들을 의미한다.

  1. C함수에 정적 변수를 선언할 수 있다.이 변수는 한 번만 초기화하고 그 값을 유지한다는 점에서 글로벌처럼 동작하는 기능에서만 볼 수 있다.이 예에서는 전화를 걸 때마다foo()그것은 점점 더 많은 숫자를 인쇄할 것이다.정적 변수는 한 번만 초기화된다.

    void foo ()
    {
    static int i = 0;
    printf("%d", i); i++
    }
    
  2. 정적(static)의 또 다른 용도는 .c 파일에서 함수 또는 전역 변수를 구현하지만 해당 기호가 .c 파일 외부에 표시되지 않도록 하는 경우 입니다..obj파일에 의해 생성됨(예:

    static void foo() { ... }
    

사람들은 C의 '정적'은 두 가지 의미가 있다고 계속 말한다.나는 그것을 보는 다른 방법을 제안한다. 그것은 하나의 의미를 부여한다.

  • 항목에 '정적'을 적용하면 해당 항목이 두 가지 속성을 갖게 된다. (a) 현재 범위 밖에서는 보이지 않는다. (b) 지속적이다.

그것이 두 가지 의미를 갖는 이유는, C에서 '정적'이 적용될 수 있는 모든 항목이 이미 이 두 가지 속성 하나를 가지고 있기 때문에, 특정한 용도는 다른 것만을 포함하는 처럼 보이기 때문이다.

예를 들어 변수를 고려하십시오.함수 외부에 선언된 변수는 이미 지속성이 있으므로(데이터 세그먼트에서), '정적'을 적용하면 현재 범위 밖(컴필레이션 단위)에는 보이지 않을 수 있다.반대로 함수 내부에 선언된 변수는 이미 현재 범위(함수) 밖에 보이지 않기 때문에 '정적'을 적용하면 지속성이 있을 뿐이다.

기능에 '정적'을 적용하는 것은 글로벌 변수에 적용하는 것과 같다 - 코드는 반드시 지속적(적어도 언어 내에서)이므로 가시성만 변경할 수 있다.

참고: 이러한 의견은 C에만 적용된다.C++에서는 클래스 메소드에 '정적'을 적용하는 것이 키워드에 다른 의미를 부여하고 있다.C99 어레이 인수 확장에서도 이와 유사하다.

다음에 따라 달라진다.

int foo()
{
   static int x;
   return ++x;
}

함수는 1, 2, 3 등을 반환하며, 변수는 스택에 있지 않다.

a.c:

static int foo()
{
}

이 함수가 이 파일에만 스코프가 있다는 뜻이다.는 A.를 할 수 .C와 B.C는 다를 수 있다.foo()s, 그리고 foo는 공유 객체에 노출되지 않는다.그래서 만약 당신이 a.c에서 foo를 정의했다면 당신은 foo에 접근할 수 없었다.b.c아니면 다른 곳에서 왔거나

대부분의 C 라이브러리에서 모든 "개인" 기능은 정적이며 대부분의 "공용"은 정적이지 않다.

위키백과에서:

C 프로그래밍 언어에서 정적(static)은 전역 변수 및 함수와 함께 그 범위를 포함하는 파일로 설정하기 위해 사용된다.로컬 변수에서는 자동으로 할당된 메모리 대신 정적으로 할당된 메모리에 변수를 저장하는 데 정적(static)이 사용된다.언어가 어느 유형의 메모리든 구현을 지시하지는 않지만, 정적으로 할당된 메모리는 일반적으로 컴파일 시 프로그램의 데이터 세그먼트에 예약되는 반면, 자동 할당된 메모리는 일반적으로 과도 통화 스택으로 구현된다.

오래된 질문에 대답하기 싫지만, K&R이 "The C Programming Language"의 A4.1절에서 어떻게 설명하는지 아무도 언급하지 않은 것 같다.

요컨대 static이라는 단어는 두 가지 의미로 쓰인다.

  1. 정적(Static)은 두 개의 스토리지 클래스 중 하나이다(다른 하나는 자동).정적 물체는 그 값을 호출 사이에 유지한다.모든 블록 외부에 선언된 물체는 항상 정적이므로 자동으로 만들 수 없다.
  2. 하지만, 언제static 키워드(코드에 키워드로 사용됨을 크게 강조함)는 선언과 함께 사용되며, 그 객체 내부 연계를 부여하여 번역 단위 내에서만 사용할 수 있다.그러나 키워드가 함수에 사용되는 경우 객체의 스토리지 클래스를 변경한다(어쨌든 객체는 해당 함수 내에서만 볼 수 있을 것이다).정적인 것의 반대는 입니다.extern키워드: 객체에 외부 연결을 부여한다.

Peter Van Der Linden은 "Expert C Programming"에서 다음과 같은 두 가지 의미를 부여한다.

  • 함수 내부에서는 통화 간 가치를 유지한다.
  • 기능 수준에서는 이 파일에만 표시됨.

함수 정적에서 변수를 선언할 경우 변수 값은 함수 호출 스택에 저장되지 않고 함수를 다시 호출할 때 계속 사용할 수 있게 된다.

글로벌 변수를 정적(static)으로 선언하면 해당 범위는 사용자가 선언한 파일 이내로 제한된다.이것은 전체 프로그램을 통해 읽고 수정할 수 있는 일반 글로벌보다 약간 안전하다.

만약 당신이 이것을 에 신고한다면mytest.c파일:

static int my_variable;

그러면 이 변수는 이 파일에서만 볼 수 있다.변수는 다른 곳으로 내보낼 수 없다.

함수 내부에서 함수를 호출할 때마다 변수 값이 값을 유지한다고 선언하는 경우

정적 함수는 파일 외부에서 내보낼 수 없다.그래서 A에서*.c파일, 정적 함수를 선언할 경우 함수 및 변수를 숨기는 경우

정적 변수는 함수에 사용할 수 있는 특수한 변수로 통화 간 데이터를 저장하며 통화 간에는 삭제하지 않는다.예를 들면 다음과 같다.

void func(void) {
    static int count; // If you don't declare its value, it is initialized with zero
    printf("%d, ", count);
    ++count;
}

int main(void) {
    while(true) {
        func();
    }
    return 0;
}

출력:

0, 1, 2, 3, 4, 5, ...

C의 정적 변수는 프로그램의 수명을 가진다.

함수에 정의되는 경우, 그들은 로컬 범위를 가지고 있다. 즉, 기능 내에서만 접근할 수 있다.정적 변수의 값은 함수 호출 간에 보존된다.

예를 들면 다음과 같다.

void function()
{
    static int var = 1;
    var++;
    printf("%d", var);
}

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

위의 프로그램에서는var데이터 세그먼트에 저장됨.그것의 수명은 전체 C 프로그램이다.

기능 종료 후 1번,var2.이 되다기능 종료 후 2번var3이 되다.

가계의 .var함수 호출 간에는 파괴되지 않는다.

만약var비 정적 변수와 국소 변수 사이에 있는 이 변수는 C 프로그램의 스택 세그먼트에 저장될 것이다.함수가 반환된 후 함수의 스택 프레임이 파괴되기 때문에 함수의 값var또한 파괴된다.

초기화된 정적 변수는 C 프로그램의 데이터 세그먼트에 저장되는 반면 초기화되지 않은 변수는 BSS 세그먼트에 저장된다.

정적 정보:변수가 글로벌하고 정적인 경우 C 프로그램의 수명 시간은 있지만 파일 범위는 있다.그것은 그 파일에서만 보인다.

이 기능을 사용하려면:

file1.c

static int x;

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

file2.c

    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

이제 다음을 사용하여 연결하십시오.

gcc -o output file1.o file2.o

그것은 x가 file1.c의 파일 범위를 가지고 있고, linker가 file2.c에서 사용되는 변수 x에 대한 참조를 해결할 수 없기 때문에 linker 오류를 줄 것이다.

참조:

  1. http://en.wikipedia.org/wiki/Translation_unit_(programming)
  2. http://en.wikipedia.org/wiki/Call_stack

기능의 정적 변수는 해당 함수에 대한 첫 번째 입력에서 초기화되며 호출이 완료된 후에도 지속된다는 점에 유의하십시오. 재귀 기능의 경우 정적 변수는 한 번만 초기화되며 모든 재귀 호출에서 그리고 심지어 해당 함수의 호출이 완료된 후에도 지속된다.

변수가 함수 외부에서 생성된 경우, 프로그래머는 변수가 선언된 소스 파일의 변수만 사용할 수 있다는 것을 의미한다.

정적 변수는 범위를 벗어난 후에도 가치를 보존하는 특성이 있다!따라서 정적 변수는 이전 범위에서의 이전 값을 보존하고 새로운 범위에서는 다시 초기화되지 않는다.

예를 들어, 프로그램을 실행하는 동안 정적 int 변수가 메모리에 남아 있는 경우를 보십시오.변수가 선언된 함수 호출이 끝나면 정상 변수나 자동 변수가 소멸된다.

#include<stdio.h> 
int fun() 
{ 
  static int count = 0; 
  count++; 
  return count; 
} 

int main() 
{ 
  printf("%d ", fun()); 
  printf("%d ", fun()); 
  return 0; 
}

출력: 1 2

1은 정적으로 선언된 대로 메모리에 남아 있기 때문에

정적 변수(전지구적 변수 등)는 명시적으로 초기화되지 않으면 0으로 초기화된다.예를 들어 아래 프로그램에서 x의 값은 0으로 인쇄되는 반면 y의 값은 쓰레기 같은 것이다.자세한 내용은 이 항목을 참조하십시오.

#include <stdio.h> 
int main() 
{ 
    static int x; 
    int y; 
    printf("%d \n %d", x, y); 
}

출력: 0 [some_garbig_value]

위에서 새로 온 사람치고는 설명되지 않은 것들이 바로 이것들이야!

다음과 같은 2가지 경우가 있다.

(1) 선언된 국소변수static 스택 대신 데이터 세그먼트에 할당됨.함수를 다시 호출해도 그 값은 유지된다.

(2) 전역변수 또는 함수가 선언됨static: 보이지 않는 컴파일 단위(즉, 링크하는 동안 기호표의 국소 기호)

C에서 정적(static)은 그 사용 범위에 따라 두 가지 의미를 갖는다.글로벌 스코프에서 개체가 파일 수준에서 선언되면 해당 파일 내에서만 해당 개체가 표시된다는 것을 의미한다.

다른 범위에서는 특정 범위를 입력하는 다른 시간 사이의 값을 유지할 개체를 선언한다.예를 들어, 절차 내에서 int를 델라코딩하는 경우:

void procedure(void)
{
   static int i = 0;

   i++;
}

'i'의 값은 절차에 대한 첫 번째 호출에서 0으로 초기화되며, 이후 절차를 호출할 때마다 값이 유지된다.'i'가 인쇄되면 0, 1, 2, 3, ...의 시퀀스를 출력할 것이다.

정적 변수 값은 서로 다른 함수 호출 간에 유지되고 해당 범위는 로컬 블록으로 제한되며 정적 변수는 항상 값 0으로 초기화된다.

C 프로그래밍에서는static가시성뿐만 아니라 수명을 모두 제어하는 예약된 키워드 입니다.만약 변수를 함수 내부의 정적인 것으로 선언한다면, 그것은 함수 전체에 걸쳐만 보일 것이다.이 사용에서, 이 정적 변수의 수명은 함수가 호출될 때 시작되고 그 함수의 실행 후에 파괴된다.다음 예제를 볼 수 있다.

#include<stdio.h> 
int counterFunction() 
{ 
  static int count = 0; 
  count++; 
  return count; 
} 

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

위 프로그램에서는 다음과 같은 출력을 제공한다.

First Counter Output = 1 
Second Counter Output = 1 

왜하하면 왜리가가 되는 이 즉시이기 이다.count = 0그리고 우리가 실행해 나가는 동안counterFunction카운트 변수를 파괴할 것이다.

참조URL: https://stackoverflow.com/questions/572547/what-does-static-mean-in-c

반응형