programing

헤더 파일의 변수 선언 - 정적입니까?

firstcheck 2022. 7. 29. 22:46
반응형

헤더 파일의 변수 선언 - 정적입니까?

#definesC++ 헤더 파일에서 다음과 같은 선언을 발견했습니다.

static const unsigned int VAL = 42;
const unsigned int ANOTHER_VAL = 37;

문제는 정전기가 발생하더라도 어떤 차이가 있느냐는 것입니다. 개 수 없습니다.는 고전적인 '알다'가 때문입니다.#ifndef HEADER #define HEADER #endif속수를

은 '1'의 합니까?VAL헤더가 여러 소스 파일에 포함된 경우 작성됩니까?

static ★★★★★★★★★★★★★★★★★」extern파일 단위 기타 변환 단위)에서 수 있는지 합니다..c ★★★★★★★★★★★★★★★★★」.cpp파일)을 클릭합니다.

  • static는 변수 내부 링크를 제공하여 다른 변환 유닛으로부터 숨깁니다.단, 내부 링크가 있는 변수는 여러 변환 단위로 정의할 수 있습니다.

  • extern는 변수 외부 링크를 제공하여 다른 변환 유닛에 표시할 수 있도록 합니다.일반적으로 변수는 하나의 변환 단위로만 정의해야 합니다.

를 하지 않은 )static ★★★★★★★★★★★★★★★★★」extern는와 C 중 입니다).

  • 파일 는 C입니다.extern디폴트로는 (하이브리드링크)가 사용됩니다.한다면 C를 사용하세요VALstatic ★★★★★★★★★★★★★★★★★」ANOTHER_VALextern.

  • 에서 파일 는 C++입니다.static 링크)로는 ( 링크)가 ( 링크)인 경우,const , , , , 입니다.extern★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★ 를 있는 는, C++ 의 양쪽 모두를 합니다.VAL ★★★★★★★★★★★★★★★★★」ANOTHER_VALstatic.

C사양서 초안:

6.2.2 식별자의 링크... -5- 함수에 대한 식별자의 선언에 스토리지 클래스 지정자가 없는 경우, 그 링크는 스토리지 클래스 지정자 외부와 함께 선언된 것과 동일하게 결정된다.개체의 식별자 선언에 파일 범위가 있고 스토리지 클래스 지정자가 없는 경우 해당 링크는 외부입니다.

C++ 사양의 초안으로부터:

7.1.1 - Storage class specificators [dcl.stc] ... -6- storage-class-specificator 없이 네임스페이스 범위에서 선언된 이름은 이전 선언으로 인해 내부 링크가 없고 const로 선언되지 않은 경우 외부 링크가 있습니다.const로 선언되고 extern으로 명시적으로 선언되지 않은 오브젝트에는 내부 링크가 있습니다.

static 1부 입니다.VAL파일이 포함된 각 소스 파일에 대해 생성됩니다.은 또한 개의 포함이 여러 을 의미하기도 합니다.VAL링크 타임에 충돌합니다.에서는 C'가 static되어 있는지 .VAL에서는 "Drughta"라고 선언되어 .extern에 ( 이니셜라이저를, 이, 이, 이, 그, 그, 그, 그를 .extern선언을 지정합니다.

static글로벌 레벨의 변수는 include를 통해 도달했는지 또는 메인 파일에 있었는지 여부에 관계없이 자체 소스 파일에만 표시됩니다.


편집자 메모:C++에서는const「」이 static 않다extern으로 「」입니다.static.

스태틱은 파일당 1개의 복사본을 얻는다는 것을 의미하지만, 다른 사람들과 달리 그렇게 하는 것이 완전히 합법적이라고 말합니다.작은 코드 샘플로 간단하게 테스트할 수 있습니다.

test.h:

static int TEST = 0;
void test();

test1.cpp:

#include <iostream>
#include "test.h"

int main(void) {
    std::cout << &TEST << std::endl;
    test();
}

test2.cpp:

#include <iostream>
#include "test.h"

void test() {
    std::cout << &TEST << std::endl;
}

이것을 실행하면, 다음의 출력이 표시됩니다.

0x446020
0x446040

constC++로 하다 이렇게 so,를 사용해서 so so so를 사용해서static과가없없 없없없다다

a.h.

const int i = 10;

1.cpp

#include "a.h"

func()
{
   cout << i;
}

2.cpp

#include "a.h"

func1()
{
   cout << i;
}

C C 프로그램에서는 ' 오류가 i( 부 ( ( ( ( ( )

이 코드 레벨에서의 정적 선언은 현재 컴파일 유닛에서만 variabel이 표시됨을 의미합니다.즉, 해당 모듈 내의 코드만이 해당 변수를 인식합니다.

변수 스태틱을 선언하는 헤더파일이 있고 그 헤더가 여러 C/CPP 파일에 포함되어 있는 경우 해당 변수는 이들 모듈에 대해 "로컬"됩니다.헤더가 포함된 N개의 위치에 대해 해당 변수의 복사본이 N개 있습니다.그들은 서로 전혀 관련이 없다.이러한 소스 파일 내의 코드는 해당 모듈 내에서 선언된 변수만 참조합니다.

이 경우 'static' 키워드는 아무런 이점이 없는 것 같습니다.제가 뭔가 놓치고 있는 것 같습니다만, 전혀 문제가 되지 않는 것 같습니다.이런 일은 전에 본 적이 없습니다.

inlining에 대해서는 이 경우 변수가 inlined로 되어 있을 가능성이 높지만 const로 선언되어 있기 때문입니다.컴파일러는 모듈 스태틱 변수를 인라인화할 가능성이 높지만 컴파일되는 상황과 코드에 따라 달라집니다.컴파일러가 'statics'를 인라인화한다는 보장은 없습니다.

C북(온라인 무료)에는 링크에 관한 장(정적)의 의미를 자세히 설명하고 있습니다(정답은 이미 다른 코멘트에 기재되어 있습니다).http://publications.gbdirect.co.uk/c_book/chapter4/linkage.html

"헤더가 여러 소스 파일에 포함된 경우 정적 VAL 복사본이 하나만 생성된다는 의미입니까?"라는 질문에 답하려면 다음과 같이 하십시오.

아니요. VAL은 헤더를 포함하는 모든 파일에 항상 개별적으로 정의됩니다.

이 경우 C와 C++의 규격에 따라 차이가 발생합니다.

C에서 파일 범위 변수는 기본적으로 extern입니다.C를 사용하는 경우 VAL은 스태틱이고 ANTHER_VAL은 extern입니다.

모던 링커는 헤더가 다른 파일에 포함되어 있는 경우(같은 글로벌 이름이 두 번 정의되어 있는 경우), ANOTHER_VAL이 다른 파일에 있는 다른 값으로 초기화되어 있는 경우 ANTHER_VAL에 대해 불평할 수 있습니다.

C++에서는 파일 범위 변수가 const일 경우 기본적으로 static이고 const일 경우 extern입니다.C++ 를 사용하고 있는 경우는, VAL 와 ANTHER_VAL 는 모두 스태틱입니다.

두 변수가 모두 상수라는 사실도 고려해야 합니다.이상적으로는 컴파일러는 항상 이러한 변수를 인라인화하고 해당 변수를 위한 스토리지를 포함하지 않는 것을 선택합니다.스토리지를 할당할 수 있는 이유에는 여러 가지가 있습니다.내가 생각할 수 있는 건...

  • 디버깅 옵션
  • 파일에 찍힌 주소
  • 컴파일러는 항상 스토리지를 할당합니다(복잡한 Const 타입은 쉽게 삽입할 수 없기 때문에 기본 타입의 특수한 케이스가 됩니다).

이러한 선언이 글로벌 범위(즉, 멤버 변수가 아님)에 있다고 가정하면 다음과 같습니다.

static은 '내부 링크'를 의미합니다.이 경우 const라고 선언되어 있기 때문에 컴파일러에 의해 최적화 또는 삽입할 수 있습니다.const를 생략하면 컴파일러는 각 컴파일 유닛에 스토리지를 할당해야 합니다.

static을 생략함으로써 링크는 기본적으로 extern이 됩니다.이 경우에도 컴파일러는 사용을 최적화/인라인화할 수 있기 때문에 사용자는 계속성 덕분에 안심할 수 있습니다.const를 드롭하면 링크 시 multiply defined symbols 오류가 발생합니다.

static 변수도 정의하지 않고 선언할 수 없습니다(스토리지 클래스 수식자 static과 extern은 서로 배타적이기 때문입니다).정적 변수는 헤더 파일에 정의할 수 있지만, 이로 인해 헤더 파일을 포함하는 각 소스 파일에 변수의 자체 개인 복사본이 생기게 되는데, 이는 의도한 바가 아닐 수 있습니다.

const 변수는 기본적으로 C++에서는 static이지만 외부 C에서는 static입니다.따라서 C++를 사용하는 경우 어떤 구성을 사용해야 하는지 알 수 없습니다.

(7.11.6 C++ 2003, Apexndix C에 샘플 있음)

C와 C++ 프로그램으로 컴파일/링크 소스를 비교하는 예:

bruziuz:~/test$ cat a.c
const int b = 22;
int main(){return 0;}
bruziuz:~/test$ cat b.c
const int b=2;
bruziuz:~/test$ gcc -x c -std=c89 a.c b.c
/tmp/ccSKKIRZ.o:(.rodata+0x0): multiple definition of `b'
/tmp/ccDSd0V3.o:(.rodata+0x0): first defined here
collect2: error: ld returned 1 exit status
bruziuz:~/test$ gcc -x c++ -std=c++03 a.c b.c 
bruziuz:~/test$ 
bruziuz:~/test$ gcc --version | head -n1
gcc (Ubuntu 5.4.0-6ubuntu1~16.04.5) 5.4.0 20160609

스태틱을 사용하면 다른 컴파일 유닛이 변수를 외부로 내보내는 것을 방지할 수 있기 때문에 컴파일러는 변수 값을 사용하는 곳에 "인라인"할 수 있고 변수용 메모리 스토리지를 만들 수 없습니다.

두 번째 예에서는 컴파일러는 다른 소스 파일이 외부로 전송되지 않는다고 가정할 수 없기 때문에 실제로 그 값을 메모리에 저장해야 합니다.

스태틱을 사용하면 컴파일러가 여러 인스턴스를 추가할 수 없습니다.이것은 #ifndef 보호에서는 덜 중요하지만 헤더가 2개의 개별 라이브러리에 포함되어 있고 애플리케이션이 링크되어 있다고 가정하면 2개의 인스턴스가 포함됩니다.

언급URL : https://stackoverflow.com/questions/92546/variable-declarations-in-header-files-static-or-not

반응형