Конфликтующее объявление функции со связью «C»

После компилируется без ошибок:

extern "C" void func( void );
extern void func( void );

Если я изменю порядок объявлений,

extern void func( void );
extern "C" void func( void );

Я получаю ошибку компилятора: conflicting declaration of ‘void func()’ with ‘C’ linkage. Стандарт С++ говорит:

  • Не более одной функции с определенным именем может быть связь "C" (независимо от пространства имен).

В обоих случаях это одна и та же функция. Я предполагаю, что компилятор С++ хранит внутри сигнатуры функций, которые он будет компилировать. В первом примере компилятор считает второе объявление допустимым и использует первое объявление для компиляции. Во втором примере это не так. Он пересматривает обе декларации как разные декларации. Какие технические детали стоят за этим? gcc 9.4.0 и msvc 19.29.30147

Что вы не понимаете?

273K 13.02.2023 17:17

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

tadman 13.02.2023 17:19

Зачем вообще нужен один func с привязкой к C++?

Ted Lyngmo 13.02.2023 17:22

@tadman Второй без extern "C" разрешен, потому что это вариант реализации в .c, где extern "C" недействителен.

273K 13.02.2023 17:22

@ 273K Я не говорю, что это не разрешено, но это непоследовательно, и это первый шаг на пути к таким проблемам. Если это создается в контексте C, вы правы, это будет проблемой, но это можно решить с помощью некоторой магии #ifdef в единственном заголовочном файле, который определяет это.

tadman 13.02.2023 17:23

Первое обнаруженное объявление extern определяет связь; вы не можете изменить связь после первоначального объявления.

molbdnilo 13.02.2023 17:24

То есть первое эквивалентно extern "C" void func( void ); extern "C" void func( void );, второе — extern "C++" void func( void ); extern "C" void func( void );

molbdnilo 13.02.2023 17:30

Я хотел бы понять, что вызывает ошибку, а не то, как это должно быть сделано. Я очень хорошо знаю, как это должно быть сделано. Это удивительный вопрос компилятора С++. Не то, как это должно быть сделано или что вы не понимаете. Я ясно сказал: я не понимаю, почему изменение порядка двух объявлений вызывает ошибку компилятора?

zdenko.s 13.02.2023 18:27
Ускорьте разработку веб-приложений Laravel с помощью этих бесплатных стартовых наборов
Ускорьте разработку веб-приложений Laravel с помощью этих бесплатных стартовых наборов
Laravel - это мощный PHP-фреймворк, используемый для создания масштабируемых и надежных веб-приложений. Одним из преимуществ Laravel является его...
Что такое двойные вопросительные знаки (??) в JavaScript?
Что такое двойные вопросительные знаки (??) в JavaScript?
Как безопасно обрабатывать неопределенные и нулевые значения в коде с помощью Nullish Coalescing
Создание ресурсов API Laravel: Советы по производительности и масштабируемости
Создание ресурсов API Laravel: Советы по производительности и масштабируемости
Создание API-ресурса Laravel может быть непростой задачей. Она требует глубокого понимания возможностей Laravel и лучших практик, чтобы обеспечить...
Как сделать компонент справочного центра с помощью TailwindCSS
Как сделать компонент справочного центра с помощью TailwindCSS
Справочный центр - это веб-сайт, где клиенты могут найти ответы на свои вопросы и решения своих проблем. Созданный для решения многих распространенных...
Асинхронная передача данных с помощью sendBeacon в JavaScript
Асинхронная передача данных с помощью sendBeacon в JavaScript
В современных веб-приложениях отправка данных из JavaScript на стороне клиента на сервер является распространенной задачей. Одним из популярных...
Как подобрать выигрышные акции с помощью анализа и визуализации на Python
Как подобрать выигрышные акции с помощью анализа и визуализации на Python
Отказ от ответственности: Эта статья предназначена только для демонстрации и не должна использоваться в качестве инвестиционного совета.
3
8
66
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Повторное объявление функции не требуется для повторения ее спецификации связи. По языковой привязке от cppreference:

Функция может быть повторно объявлена ​​без спецификации привязки после того, как она была объявлена ​​со спецификацией языка, второе объявление будет повторно использовать первую привязку к языку. Обратное неверно: если первое объявление не имеет языковой привязки, предполагается "C++", а повторное объявление с другим языком является ошибкой.

В первом фрагменте вы объявляете функцию с привязкой "C", а затем повторно объявляете ее без явной привязки. Это нормально; исходная связь предполагается. Однако во втором фрагменте вы объявляете функцию с (неявной) связью "C++", а затем пытаетесь повторно объявить ее с помощью связи "C" — это конфликт, отсюда и ошибка.

Это именно то, что я искал. Часть ссылки на cpp, которая объясняет, почему важен порядок объявления. Ответ в «Противоположное неверно:»

zdenko.s 13.02.2023 18:31

Другие вопросы по теме