G ++에 의해 무시되고 :통근 const를 연동 규격은 겉으로 나는이 평행 C++ 컴파일러와 C 코드베이스를 구축하는 상황이
lib.h
extern int const values[2] = {1, 2};
lib.c
#include "lib.h"
main.c를
#include <iostream>
extern int const values[2];
int main() {
std::cout << values[0] << ":" << values[1] << std::endl;
}
C++03 Standard Annex C Compatibility C.1.2 Clause 3에 지적 된 사항 때문에 extern을 추가해야했습니다.
$ objdump -t lib.o | grep values
0000000000000000 l O .rodata 0000000000000008 _ZL6values
$ objdump -t main.o | grep values
0000000000000000 *UND* 0000000000000000 values
을 ... 그리고 그것은 같다 : 는 extern
전에
이 덧붙여이 values
은 objdump를에 표시되는 방법에하게 차이가 이런 식이다 (. -fpermissive
로 컴파일하면 양탄자에 따라 본을 쓸어)
$ objdump -t lib.o | grep values
0000000000000000 g O .rodata 0000000000000008 values
$ objdump -t main.o | grep values
0000000000000000 *UND* 0000000000000000 values
, 우리는 "L"는 "G"로 전환을 그래서 이름 맹 글링이 떨어졌다보고, 링커에 대한 0,123,402,576 불평하지 않습니다 :이은을 첨가 한 후이 정의되지 않았습니다.
지금 같은 방식으로 수정이 개 매우 유사한 파일과 같은 상황을 상상 :
TMP-exttypes.h
extern const REBYTE Reb_To_RXT[REB_MAX] = { /* bunch of stuff */ };
A-lib.c
extern const REBYTE Reb_To_RXT[REB_MAX];
다음은 프로젝트에서 Reb_To_RXT 정의는 두 개만 만들어졌으며 깨끗하게 만들었습니다. 그러나 연결 아니에요 나는 그것을 언급하는 유일한 두 개의 파일을 objdump를 할 때 내가 얻을 :
$ objdump -t a-lib.o | grep Reb_To_RXT
00000000 *UND* 00000000 Reb_To_RXT
$ objdump -t f-extension.o | grep Reb_To_RXT
00000080 l O .rodata 00000038 _ZL10Reb_To_RXT
그것은 L 말한다, 그리고 이름 엉망입니다. 어느 것이 훨씬 간단한 예제를 행복하게 만들지 못했습니다. 그러나 나는 이것이 외모가 생길 때 어떻게 외계인이 일어날 수 있는지 궁금합니다. 나는 이것이 총기류라고 믿는 것이 옳은가? 그리고 일반적으로 extern으로 선언 된 것만이 국부적 인 연계성을 가져서는 안되는 것이 일어날 것이라고 생각하지는 않는가?
프로토 타입 그리고 내가 그것을했을 거라고 어떻게 물론 하나의 정의를 선호하는 것입니다. 하지만 내가 적응하고있는 코드는 다른 사람의 C 다. 그리고 그것을 바꿀 수있는 힘든 싸움이 될 수도있다. 하지만 C조차도 UB라는 표제가 있다면 더 많은 탄약이있을 수 있습니다 ...? :/ – HostileFork
@HostileFork C++ 11에서는 배열을'constexpr'로 선언하고 초기화 할 수 있습니다. 그러나 글로벌 객체를 두 번 정의하면 ODR을 위반하게되며 즉시 UB가됩니다. – Potatoswatter
@HostileFork : C99, §6.9/5의 마지막 초안 (N869) : "외부 정의는 함수 또는 객체의 정의이기도 한 외부 선언입니다. 외부 연결로 선언 된 식별자가 사용 된 경우 표현식 (sizeof 연산자의 오퍼랜드의 일부로 제외)에서 전체 프로그램 어딘가에 식별자에 대한 하나의 외부 정의가 있어야하며, 그렇지 않은 경우에는 하나만 존재해야합니다. " 나중의 표준 인 C11이 있지만 근본적인 것이 바뀌 었다고 상상할 수는 없습니다. MSVC는 C89 (C99가 아니라 C89가 아닙니다)를 구현합니다 ... –