Когда использовать внешние слова "С" простыми словами?

Возможно, я не понимаю различия между C и С++, но когда и зачем нам нужно использовать

extern "C" {

? По-видимому, это "соглашение о связи".

Я кратко прочитал об этом и заметил, что все файлы заголовков .h, входящие в состав MSVS, окружают его код. Какой тип кода является "C-кодом", а не "кодом С++"? Я думал, что С++ содержит все C-коды?

Я предполагаю, что это не так, и что С++ отличается и что стандартные функции/функции существуют в том или ином, но не в обоих (то есть: printf есть C, а cout - С++), но С++ - назад совместимый, хотя внешняя декларация "С". Правильно ли это?

Мой следующий вопрос зависит от ответа на первый, но я все равно его спрошу: поскольку файлы заголовков MSVS, написанные на C, окружены extern "C" {...}, когда вам когда-нибудь понадобится использовать это самостоятельно в своем собственном коде? Если ваш код является C-кодом, и вы пытаетесь его скомпилировать в компиляторе С++, не стоит ли работать без проблем, потому что все стандартные h файлы, которые вы включили, уже будут иметь внешнюю "C" в них с помощью компилятора С++?

Вам нужно использовать это при компиляции на С++, но связываясь с уже построенными библиотеками C или что-то в этом роде?

18
задан 09 мая '10 в 9:11
источник поделиться
7 ответов

Вам нужно использовать extern "C" в С++ при объявлении функции, которая была реализована/скомпилирована в C. Использование extern "C" указывает компилятору/компоновщику использовать соглашения об именах и вызовах C, а не имя языка С++ и С++, которые будут использоваться иначе. Для функций, предоставляемых другими библиотеками, вам почти никогда не понадобится использовать extern "C", так как у хорошо написанных библиотек уже есть это для публичных API, которые он экспортирует как на C, так и на С++. Если, однако, вы пишете библиотеку, которую хотите сделать доступной как на C, так и на С++, тогда вам придется условно поместить ее в свои заголовки.

Что касается всего кода C кода С++... нет, это неверно. Популярным мифом является то, что С++ является "надмножеством C". Хотя С++, безусловно, стремится быть максимально совместимым с C, существуют некоторые несовместимости. Например, bool является допустимым С++, но не является допустимым C, а _Bool существует в C99, но недоступен в С++.

В отношении того, вам когда-нибудь понадобится использовать extern "C" с системными ".h" файлами... любая хорошо продуманная реализация будет иметь те, что есть для вас, так что вам не нужно их использовать, Однако, чтобы быть уверенным, что они предоставлены, вы должны включить эквивалентный заголовочный файл, начинающийся с "c" и пропуская ".h". Например, если вы включите < ctype.h > , то почти любая разумная система будет иметь добавленный extern "C"; однако, чтобы быть уверенным в совместимом с С++ заголовке, вы должны вместо этого включить заголовок <cctype> .

Вы также можете быть заинтересованы в Смешивание C и С++ с С++ FAQ Lite.

21
ответ дан 09 мая '10 в 9:14
источник

Другие ответы верны, но, вероятно, поможет полный "шаблонный" пример. Канонический метод включения кода C в проекты C и/или С++ выглядит следующим образом:

//
// C_library.h
//

#ifdef __cplusplus
extern "C" {
#endif

//
// ... prototypes for C_library go here ...
//

#ifdef __cplusplus
}
#endif

-

//
// C_library.c
//

#include "C_library.h"

//
// ... implementations for C_library go here ...
//

-

//
// C++_code.cpp
//

#include "C_library.h"
#include "C++_code.h"

//
// ... C++_code implementation here may call C functions in C_library.c ...
//

Примечание. Вышеупомянутое также относится к вызову кода C из Objective-C ++.

15
ответ дан 09 мая '10 в 9:58
источник

Компиляторы С++ калечат имена в своей таблице символов иначе, чем компиляторы C. Вы должны использовать объявление extern "C", чтобы сообщить компилятору С++ использовать соглашение о слиянии C вместо этого при создании таблицы символов.

9
ответ дан 09 мая '10 в 9:13
источник
Блоки

extern "C" {} сообщают компилятору С++ использовать соглашения об именах и вызовах C. Если вы этого не сделаете, вы получите ошибки компоновщика, если попытаетесь включить библиотеку C в свой проект на С++, потому что С++ будет калечить имена. Я использую это во всех своих заголовках на всякий случай, когда они когда-либо используются в проекте С++:

#ifdef __cplusplus
extern "C" {
#endif

/* My library header */

#ifdef __cplusplus
} // extern
#endif
2
ответ дан 09 мая '10 в 9:25
источник

Я использую "extern c", чтобы С# мог читать мой код на С++, не вычисляя лишнее имя, выполняемое при экспорте функции dll С++. В противном случае есть лишние бессмысленные (или действительно неанглийские) символы, которые я должен добавить в конце точки входа функции на стороне С# для правильного доступа к функции С++ в dll.

2
ответ дан 09 мая '10 в 9:24
источник

Вам нужно использовать extern "C", если вы хотите использовать соглашение C-вызова в коде, скомпилированном компилятором С++. Для этого есть две причины:

  • У вас есть функция, реализованная в C, и вы хотите вызвать ее из С++.

  • У вас есть функция, реализованная на С++, и вы хотите вызвать ее из C. Обратите внимание, что в этом случае вы можете использовать только C-часть С++ в интерфейсе функций (без классов,...).

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

Обычно объявления в заголовочном файле C окружены

#ifdef __cplusplus
extern "C" {
#endif

[... C declarations ...]

#ifdef __cplusplus
}
#endif

чтобы сделать его пригодным для использования с С++.

1
ответ дан 09 мая '10 в 9:37
источник

Функции С++ подчиняются name mangling. Это делает невозможным вызов непосредственно из кода C, если не используется extern "C".

0
ответ дан 09 мая '10 в 9:12
источник

Другие вопросы по меткам или Задайте вопрос