Intereting Posts

Почему определения структуры имеют внутреннюю связь?

(Я говорю о C, но это также относится к шаблонам classов в C ++)

В заголовочном файле принято ставить все ДЕКЛАРАЦИИ, а не определения. Тем не менее, мы обычно помещаем определения структуры или шаблоны classов в заголовочный файл, не зная, почему мы можем. Это не имеет смысла, потому что они также являются определениями – ПРАВИЛО ОДНОГО ОПРЕДЕЛЕНИЯ. (Да, определения структуры и шаблоны classов не приводят к установке какого-либо хранилища, но вы по-прежнему получаете ошибку «переопределения», ниже которой подразумевается, что они являются определениями).

EX), определяющий несколько структур с одним и тем же тегом внутри одного файла, дает вам ошибку переопределения, но определение нескольких структур с одним и тем же тегом в нескольких исходных файлах не вызывает ошибки (то же самое происходит с classом).

Единственное, что имеет смысл, это то, что определения структуры и шаблоны classов имеют внутреннюю связь (в отличие от внешней привязки по умолчанию), но я не могу найти никаких ссылок на нее в K & R или справочном руководстве. На самом деле, структуры даже не упоминаются в связи.

Я хочу знать точную ссылку, где стандарт ANSI указывает на этот феномен. (IMO, это довольно двусмысленная вещь, о которой следует упомянуть в стандарте ANSI).


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

Я спрашиваю, почему размещение определения структуры в файле заголовка не приведет к ошибке переопределения, как это происходит, когда мы помещаем определения переменных в заголовочный файл (и включаем его в несколько исходных файлов)

EX) test1.c: int a = 3; test2.c: int a = 4; Вызывает ошибку компиляции из-за переопределения. Тем не мение,

test1.c: struct test {int a}; test2.c: struct test {int b}; Не вызывает ошибку компиляции, и единственная причина, по которой я могу придумать, состоит в том, что определения структуры либо имеют внутреннюю связь, либо вообще не связаны.

В C только объекты и функции имеют связь. Поскольку struct в C не может содержать функции или « static » объекты-члены, как в C ++, ваш вопрос не имеет большого смысла.

Функции-члены в C ++ до тех пор, пока они не определены, но объявлены внутри struct без проблем. Если они также определены, они являются inline . Концепция inline была только что изобретена для C ++, чтобы зафиксировать этот случай: определение функции, которое может быть передано через файл заголовка в нескольких единицах компиляции. C99, который принял эту концепцию (слегка ее изменив).

static объекты-члены действительно представляют большую проблему. Синтаксис создания экземпляров этих парней довольно неясен, особенно для class template es или struct s. Если вы хотите узнать об этом, вам придется просить об этом, помеченном специально на C ++.

Строка структуры – это просто определение. Определение не видно за пределами исходного файла.
FYI: ни файл-источник ничего не экспортирует.

Чтобы проверить это:

 $ cat test1.c struct test { char a; }; $ gcc -o test1.o -c test1.c $ nm $ echo "struct test foo; " >> test1.c $ gcc -o test1.o -c test1.c $ nm 0000000000000001 C _foo 

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

Обычными вещами для них являются декларации перечислений, typedefs, structs и прототипов функций, поэтому различные C-файлы могут компилироваться без необходимости знать фактическую функцию или фактическую память (структура в основном является определением того, как выделяется память)

Структуры определены в файле заголовка, потому что заголовочный файл предоставляет интерфейс для модуля. Когда структура определена в интерфейсе, пользователи интерфейса могут:

  • обратитесь к членам структуры
  • знать, насколько велика структура – иначе они не могли бы выделить память для структуры

Связь не имеет к этому никакого отношения – связаны только функции, а не структуры данных.

Обратите внимание, что вы все равно можете объявить структуру в файле заголовка, что полезно, если вы хотите скрыть внутренние структуры (непрозрачную структуру данных). Пользователи интерфейса могут иметь указатели на структуру и использовать их как своего рода cookie, но они не могут выделить такую ​​структуру самостоятельно или «видеть» внутри нее.

Что касается не получения ошибки переопределения при определении структуры в файле заголовка, это просто из-за защиты заголовков – заголовок обычно выглядит следующим образом:

 #ifdef MYHEADER_H #define MYHEADER_H struct a { int x; } void f(void); /* and so on */ #endif 

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

У меня нет копии окончательной версии, но из черновика спецификации n843 я вижу:

из 6.7.2.3 Тэги : «4 Два объявления структуры, объединения или перечисляемые типы, которые находятся в разных областях или используют разные tags, объявляют разные типы. Каждое объявление структуры, объединения или перечисляемого типа, которое не включает тег, объявляет особый тип “.

из 6.2.1. Области идентификаторов : «4 Каждый другой идентификатор имеет область определения, определяемую размещением его декларации (в указателе или типе). Если декларатор или тип спецификатора, объявляющий идентификатор, отображается вне любого блока или списка параметров , идентификатор имеет область видимости , которая заканчивается в конце единицы перевода. […] “[выделение в оригинале] (Единственным типом идентификатора, который я вижу в этом разделе перед этим утверждением, были метки, которые имеют функцию объем.)

Я не эксперт по C или стандартам, но мне кажется, что это объясняет поведение, которое вы видите. Таким образом, структура должна иметь столкновение, если область содержимого одинакова, а структура имеет повторяющийся тег, потому что для создания разных типов потребуется отдельный ярлык. Но если они находятся в другом объеме файлов, нет никаких проблем, поскольку, если они находятся в разных областях, требования удовлетворяются за то, что они являются особым типом.