2014-12-31 2 views
7

Я экспериментировал с GCC и обнаружил, что вы можете объявлять внешние переменные const в заголовочных файлах, но сохраняйте их изменяемыми в файлах реализации.Объявление глобальной переменной `extern const int` в заголовке, но только` int` в исходном файле

EDIT: Это действительно не работает. Единственная причина, по которой я получил свой тестовый код для компиляции, состояла в том, что я не включил «header.h» в «header.c».

header.h:

#ifndef HEADER_H_ 
#define HEADER_H_ 

extern const int global_variable; 

#endif 

header.c:

int global_variable = 17; 

Это кажется очень хорошая особенность, чтобы использовать для хранения global_variable чтения для пользователей header.h но держать их modifable самая осуществление (header.c).

ПРИМЕЧАНИЕ: Следующий код является лишь примером того, как этот способ объявления предотвратит присвоение global_variable.

#include "header.h" 

int main(void) 
{ 
    global_variable = 34; /* This is an error as `global_variable` is declared const */ 
    return 0; 
} 

Потому что я никогда не видел техники на практике раньше. Я начинаю задаваться вопросом, действительно ли это.

Является ли это четко определенным поведением или это ошибка, о которой GCC не предупреждает меня?

+0

Какая точная формулировка ошибки (скопируйте и вставьте ее)? –

+0

Я бы сбила с толку, что переменная const может вообще измениться. Я бы ограничил область с помощью static и предоставил функцию, чтобы вернуть текущее глобальное значение, чтобы получить тот же эффект. – ryanpattison

+1

Единственный способ, которым это может работать, - это если заголовок // не включен ** в header.c. Если включить header.h в header.c, то присваивание ** будет ** давать синтаксическую ошибку. Если это делается в реальной программе с 1000-ю строками кода, а что-то не так - как легко это исправить? –

ответ

6

const int и int не подходят.

Например это:

extern const int a; 

int a = 2; 

не действует в С, как говорит, что С:

(С11, 6.7p4) «Все декларации в той же области, которые относятся к одному объекту или функция должны указывать совместимые типы »

В вашем случае они не в той же сфере (разные единицы перевода), но C также говорит, что:

(C11, 6.2.7p2) «Все объявления, относящиеся к одному объекту или функции, должны иметь совместимый тип; В противном случае поведение не определено.»

Как вы нарушаете правило выше, вы призываете к неопределенному поведению.

Обратите внимание, что C90 имеет те же самые пункты.

+0

Я думаю, что OP _counting_ на нем не компилируется. Если код не компилируется, нет UB. – chux

+0

@chux Я не понимаю, не могли бы вы уточнить? Я думаю, что OP будет компилировать и связывать 'header.c' и' main.c' вместе (иначе у вас нет определения для объекта). – ouah

+0

NMDV, но OP, похоже, знает, что код 'main.c' не компилируется. Реальный вопрос: может ли не-const-переменная быть объявлена ​​как не-const в одном модуле, а const - в другом? – chux

0

Вы не присваивание значения к global_variable, вы определяете его.

1

немного поздно, но в любом случае.

Я думаю, что это может работать, если вы делаете что-то вроде этого

в заголовке.ч:

#ifndef HEADER_H_ 
#define HEADER_H_ 

#ifndef HAS_GLOB_VAR 
extern const int global_variable; 
#endif 

#endif 

и если вам необходимо включить заголовок в файле, который фактически определяет переменную (header.c) вы делаете что-то вроде

#define HAS_GLOB_VAR 
#include "header.h" 

int global_variable = 17; 

... 

На других файлов, которые вы просто включите заголовок и дон 't определить HAS_GLOB_VAR.

+2

Хм, это UB per (C11, 6.2.7p2) «Все объявления, относящиеся к одному и тому же объекту или функции, должны иметь совместимый тип, иначе поведение не определено». – chux

Смежные вопросы