Programing

외부와 콘스탄트 혼합

c10106 2022. 5. 16. 20:12
반응형

외부와 콘스탄트 혼합

내가 외측과 외측을 혼용할 수 있을까?만약 그렇다면, 순경 한정자는 그것이 선언된 범위 내에서만 그것의 통치를 강요하는가 아니면 그것이 선언된 번역 단위의 선언과 정확히 일치해야 하는가?즉, 다음과 같이 말할 수 있다.extern const int i;심지어 실제 는 항상이 아니고 그 반대일때도?

  • 응, 같이 써도 돼.
  • 그리고 그래, 실제로 신고된 번역단위의 선언과 정확히 일치해야 해.물론 당신은 언더핸드 C 프로그래밍 대회에 참가하지 않는 한:-)

일반적인 패턴:

  • file.h:
    extern const int a_global_var;
  • file.c:
    #include "file.h"
    const int a_global_var = /* some const expression */;

편집: 범례2k의 주석 삽입.고마워요.

C++17inline변수들

만약 당신이 원한다고 생각한다면extern const그러면 C++17 인라인 변수를 실제로 사용할 가능성이 더 높다.

이 놀라운 C++17 기능을 통해 다음을 실현하십시오.

  • 각 상수에 대해 하나의 메모리 주소만 편리하게 사용
  • 그것을 a로 저장하다.constexpr: Constexpr 외부 신고 방법?
  • 한 머리글에서 한 줄로 하다.

main.cpp

#include <cassert>

#include "notmain.hpp"

int main() {
    // Both files see the same memory address.
    assert(&notmain_i == notmain_func());
    assert(notmain_i == 42);
}

주체가 아닌hpp

#ifndef NOTMAIN_HPP
#define NOTMAIN_HPP

inline constexpr int notmain_i = 42;

const int* notmain_func();

#endif

notmain.cpp

#include "notmain.hpp"

const int* notmain_func() {
    return &notmain_i;
}

컴파일 및 실행:

g++ -c -o notmain.o -std=c++17 -Wall -Wextra -pedantic notmain.cpp
g++ -c -o main.o -std=c++17 -Wall -Wextra -pedantic main.cpp
g++ -o main -std=c++17 -Wall -Wextra -pedantic main.o notmain.o
./main

기트허브 상류.

참고 항목:인라인 변수는 어떻게 작동하는가?

인라인 변수의 C++ 표준

C++ 표준은 주소가 동일함을 보증한다.C++17 N4659 표준 초안 10.1.6 "인라인 지정자":

6 인라인 함수 또는 외부 연결이 있는 변수는 모든 변환 단위에서 동일한 주소를 가져야 한다.

cppreference https://en.cppreference.com/w/cpp/language/inline은 다음과 같이 설명한다.static주어지지 않고, 그러면 그것은 외부적인 연계가 있다.

인라인 변수 구현

다음을 통해 구현 방법을 관찰할 수 있다.

nm main.o notmain.o

다음을 포함하는:

main.o:
                 U _GLOBAL_OFFSET_TABLE_
                 U _Z12notmain_funcv
0000000000000028 r _ZZ4mainE19__PRETTY_FUNCTION__
                 U __assert_fail
0000000000000000 T main
0000000000000000 u notmain_i

notmain.o:
0000000000000000 T _Z12notmain_funcv
0000000000000000 u notmain_i

그리고man nm에 대해 말하다.u:

"u" 기호는 고유한 글로벌 기호다.이것은 ELF 기호 바인딩의 표준 집합에 대한 GNU 확장이다.그러한 기호의 경우 동적 링커는 전체 프로세스에서 이 이름과 유형을 가진 기호가 하나만 사용되도록 할 것이다.

그래서 우리는 이것을 위한 ELF 전용 확장이 있다는 것을 알 수 있다.

C++ 17 이전:extern const

extern const아래 예시와 같이 작동하지만, 에 대한 단점은 다음과 같다.inline다음과 같다:

  • 변수를 만드는 것은 불가능하다.constexpr 이 기지로만inline다음을 허용한다.외부 신고는 어떻게 하지?
  • 헤더와 cpp 파일에서 변수를 별도로 선언하고 정의해야 하므로 품위가 떨어진다.

main.cpp

#include <cassert>

#include "notmain.hpp"

int main() {
    // Both files see the same memory address.
    assert(&notmain_i == notmain_func());
    assert(notmain_i == 42);
}

notmain.cpp

#include "notmain.hpp"

const int notmain_i = 42;

const int* notmain_func() {
    return &notmain_i;
}

주체가 아닌hpp

#ifndef NOTMAIN_HPP
#define NOTMAIN_HPP

extern const int notmain_i;

const int* notmain_func();

#endif

기트허브 상류.

C++17 이전 헤더만 사용할 수 있음

이것들이 더 좋은 것 같지는 않다.extern솔루션, 그러나 단일 메모리 위치만 차지하며,

A constexpr함수를 의미하기 때문에inline 모든 번역 장치에 정의가 나타나도록 허용(수정):

constexpr int shared_inline_constexpr() { return 42; }

제대로 된 컴파일러라면 호출에 줄을 서겠지

또한 a를 사용할 수 있다.const또는constexpr다음과 같은 정적 정수 변수:

#include <iostream>

struct MyClass {
    static constexpr int i = 42;
};

int main() {
    std::cout << MyClass::i << std::endl;
    // undefined reference to `MyClass::i'
    //std::cout << &MyClass::i << std::endl;
}

그러나 주소를 가져가는 등의 작업을 수행할 수 없으며, 그렇지 않으면 https://en.cppreference.com/w/cpp/language/static "Constant static members" 및 constexpr 정적 데이터 구성원 정의를 참조하십시오.

완전히 인라인으로 할 수 있는 방법은?

TODO: 메모리를 전혀 사용하지 않고 변수를 완전히 인라인으로 연결할 수 있는 방법이 없을까?

전처리가 하는 것과 비슷해

이 작업에는 어떻게든 다음과 같은 사항이 필요하다.

  • 변수의 주소를 사용하는지 여부를 탐지하거나 금지
  • 이 정보를 ELF 개체 파일에 추가하고 LTO가 이를 최적화하도록 하십시오.

관련:

Ubuntu 18.10, GCC 8.2.0에서 시험하였다.

그것들을 함께 사용할 수 있다.그러나 C++가 이름 장식을 할 때 기호 이름을 장식하는 데 사용되는 유형 정보에 항상 포함되기 때문에 항상성을 사용할 필요가 있다.그렇게extern const int i와 다른 변수를 언급할 것이다.extern int i

외부 "C" {}을(를) 사용하지 않는 한, C 이름 장식은 const에 주의를 기울이지 않는다.

당신은 그것들을 함께 사용할 수 있고 당신은 항상 키워드를 무시하는 모든 종류의 일들을 할 수 있다. 왜냐하면 그것뿐이기 때문이다. 키워드.그것은 컴파일러에게 변수를 변경하지 않을 것이라고 말해 컴파일러가 유용한 선택을 할 수 있게 하고 의도하지 않았던 것들을 바꾸는 것을 멈추게 한다.

아마존닷컴은 좀 더 많은 배경을 가진 괜찮은 기사를 가지고 있다.

응, 같이 써도 돼.

만약 당신이 "external const in i"를 선언한다면, 나는 그것의 전체 범위를 넘어설 것이다.그것을 불변으로 재정의하는 것은 불가능하다.물론 const 플래그를 던져 버림으로써(const_cast 사용) 우회할 수 있다.

참조URL: https://stackoverflow.com/questions/2190919/mixing-extern-and-const

반응형