спецификация extern const linking игнорируется G ++

У меня есть ситуация, строящая кодовую базу 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 Стандартное приложение C Совместимость C.1.2 Пункт 3. (Компиляция с -fpermissive смести это под коврик.)

Между прочим, разница в том, как values появляется в objdump, как это до extern:

$ objdump -t lib.o | grep values
0000000000000000 l     O .rodata    0000000000000008 _ZL6values

$ objdump -t main.o | grep values
0000000000000000         *UND*  0000000000000000 values

…и затем это так после того, как он добавлен:

$ objdump -t lib.o | grep values
0000000000000000 g     O .rodata    0000000000000008 values

$ objdump -t main.o | grep values
0000000000000000         *UND*  0000000000000000 values

Таким образом, искажение имени было удалено, мы видим, что буква «L» превращается в букву «G», и компоновщик не жалуется на values быть неопределенным.


Теперь представьте ту же ситуацию с двумя очень похожими файлами, измененными таким же образом:

ТМП-exttypes.h

extern const REBYTE Reb_To_RXT[REB_MAX] = { /* bunch of stuff */ };

а-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, не должно иметь где-либо локальную связь?

1

Решение

я не могу понять, что ты просить.

но …

имеющий

extern int const values[2] = {1, 2};

в заголовочном файле у вас есть UB, если этот заголовок включен в более чем одну единицу перевода. скорее всего, но не обязательно, вы получите ошибку компоновки.

одно решение: объявить массив в заголовке, как

extern int const values[2];

но определите его (с инициализатором) в файле реализации.

Другое решение состоит в том, чтобы использовать шаблонный трюк или трюк встроенных функций для определения массива в заголовочном файле.

уловка встроенной функции:

typedef int const Values[2];

inline Values& valuesRef()
{
static Values   theValues = {1, 2};
return theValues;
}

static Values& values = valuesRef();
3

Другие решения

Да исправить.

Файл, который вы (я) редактировали, был автоматически сгенерирован и фактически уничтожен чистым изготовителем, который был замечен на полпути при записи мыслительного процесса. Эта «tmp», которую вы видите в этом конкретном заголовке, должна была указывать на «временный, не редактировать», и если файл не перезагружается в редакторе, который вы используете, он может сбить с толку.

(Закончил ход мыслей в любом случае для институциональных знаний. :-P)

1

По вопросам рекламы [email protected]