Для чего нужен extern c
Зачем нужен extern?
Зачем нужен dynamic_cast?
Point * mas; mas = new Point(); mas = new Square(); mas = new Circle();.
Объяснить зачем нужен i
#include #include using namespace std; int main() < cout 10
Нет. переменная а с этого момента уже определена, но не инициализирована, ее значение задано по умолчанию.
Посмотрите в окне отладчика.
extern нужен например для того, чтобы обращаться к переменной, определенной в другом файле исх. кода.
Функции по дефолту extern.
Поправочка: В этом случае компоновщик выдаст сообщение.
Добавлено через 48 секунд
Вам сюда: Используете ли вы глобальные переменные свежак
Добавлено через 2 минуты
Если объявления нет, тогда компилятор не будет знать что это такое вообще,
никакие определения искать не будет, тем более,
выдавать ошибки о том, что определение не найдено.
Он будет ругаться на отсутствие объявления.
P.S. Выше я немного не так выразился, возможно несколько не понятно
Каков эффект extern «C» в C++?
что именно делает putting extern «C» в C++ код делать?
13 ответов:
extern » C «делает имя функции в C++ с привязкой» C «(компилятор не искажает имя), чтобы код клиента C мог ссылаться на (т. е. использовать) вашу функцию, используя совместимый с » C » файл заголовка, который содержит только объявление вашей функции. Ваше определение функции содержится в двоичном формате (который был скомпилирован вашим компилятором C++), что клиентский компоновщик » C «будет ссылаться на использование имени «C».
просто чтобы вы знали, вы можете указать связь «C» с каждым отдельным объявлением / определением явно или используйте блок для группировки последовательности объявлений / определений, чтобы иметь определенную связь:
Если вы заботитесь о технических особенностях, они перечислены в разделе 7.5 стандарта C++03, вот краткое резюме (с акцентом на extern «C»):
просто хотел добавить немного информации, так как я не видел еще в курсе.
вы очень часто будете видеть код в заголовках C, например:
это позволяет вам использовать этот файл заголовка C с вашим кодом C++, потому что будет определен макрос «__cplusplus». Но вы можете и все еще используйте его с вашим устаревшим кодом C, где макрос не определено, поэтому он не будет видеть однозначно C++ строить.
хотя, я также видел C++ код, такой как:
, Я думаю, выполняет почти то же самое.
Не уверен, какой путь лучше, но я видел обоих.
в каждой программе на C++ все нестатические функции представлены в двоичном файле в виде символов. Эти символы представляют собой специальные текстовые строки, которые однозначно идентифицируют функцию в программе.
В C, имя символа совпадает с именем функции. Это возможно, потому что в C никакие две нестатические функции не могут иметь одно и то же имя.
потому что C++ допускает перегрузку и имеет много функций, которые C не любит-классы, функции-члены, спецификации исключений-это невозможно просто использовать имя функции в качестве имени символа. Чтобы решить эту проблему, C++ использует так называемое искажение имени, которое преобразует имя функции и всю необходимую информацию (например, количество и размер аргументов) в какую-то странную строку, обрабатываемую только компилятором и компоновщиком.
поэтому, если вы укажете функцию, которая будет extern C, компилятор не выполняет искажение имени с ней, и это может быть напрямую доступ с использованием его имени символа в качестве функции имя.
это удобно при использовании dlsym() и dlopen() для вызова таких функций.
декомпилировать a g++ двоичный файл, чтобы увидеть, что происходит
компиляция с выходом GCC 4.8 Linux ELF:
декомпилировать таблицу символов:
толкование
ef и eg хранились в символах с тем же именем, что и в код
остальные символы были искажены. Давайте распутаем их:
вывод: оба из следующих типов символов не mangled:
так что вам понадобится extern «C» как при вызове:
вещи, которые не работают в extern C
становится очевидным, что любая функция C++, которая требует искажения имени, не проснется внутри extern C :
минимальный запускаемый C из примера C++
для полноты картины и для новичков там.
вызов C из C++ довольно прост: каждая функция C имеет только один возможный неискаженный символ, поэтому никакой дополнительной работы не требуется.
без extern «C» ссылка не работает с:
минимальный запускаемый C++ из примера C
вызов C++ из немного сложнее: мы должны вручную создавать не искаженные версии каждой функции, которую мы хотим выставить.
здесь мы проиллюстрируем, как предоставить перегрузку функций C++ С.
без extern «C» выдает:
, потому что g++ генерируются искаженные символы, которые gcc не удается найти.
C++ искажает имена функций для создания объектно-ориентированного языка из процедурного языка
давайте посмотрим на следующие пример:
компилятор C не будет компилировать приведенный выше пример, потому что та же функция printMe определяется дважды (хотя они имеют разные параметры int a vs char a ).
gcc-o printMe printMe.с. && /printMe;
Ошибка 1. PrintMe определяется несколько раз.
компилятор C++ скомпилирует приведенный выше пример. Ему все равно, что printMe определен дважды.
это потому, что компилятор C++ неявно переименовывает (mangles) функции, основанные на их параметры. В C, эта функция не поддерживается. Однако, когда C++ был построен на C, язык был разработан, чтобы быть объектно-ориентированным, и должен был поддерживать возможность создавать различные классы с методами (функциями) того же имени и переопределять методы (способ переопределения) основан на разные параметры.
Extern говорит «не калечить имена функций»
однако, представьте, что у нас есть унаследованный C-файл с именем «parent.c » это include имена функций s из других устаревших файлов C, » parent.ч», «ребенок.h » и др. Если наследство » родитель.файл c » запускается через компилятор C++, затем имена функций будут искажены, и они больше не будут соответствовать именам функций, указанным в «parent.ч», «ребенок.h » и т. д.-Поэтому имена функций в этих внешних файлах также понадобятся быть искалеченным. Искажение имен функций в сложной программе на C, имеющей множество зависимостей, может привести к нарушению кода; поэтому может быть удобно предоставить ключевое слово, которое может сказать компилятору C++ не искажать имя функции.
The extern ключевое слово говорит компилятору C++ не калечить (переименовывать) имена функций. Пример использования: extern void printMe(int a);
оно меняет взаимосвязи функции таким образом, что функция вызывается из C. На практике это означает, что имя функции не mangled.
Не любой c-заголовок будет компилироваться с extern «C». Когда идентификаторы в C-заголовке конфликтуют с ключевыми словами C++, компилятор C++ будет жаловаться на это.
например, я видел следующий код сбой в g++:
вроде имеет смысл, но это то, что нужно иметь в виду при портировании C-кода на C++.
Он сообщает компилятору C++, чтобы искать имена этих функций в стиле C при связывании, потому что имена функций, скомпилированных в C и C++, отличаются на этапе связывания.
extern «C» предназначен для распознавания компилятором C++ и уведомления компилятора о том, что указанная функция (или должна быть) скомпилирована в стиле C. Так что при связывании, это ссылка на правильную версию функции из C.
я использовал модификатор extern «с», Перед для DLL(динамически подключаемая библиотека) файлы и т. д. функция main ()» exportable», поэтому ее можно использовать позже в другом исполняемом файле из dll. Может быть, пример того, где я использовал его, может быть полезен.
Тип 1:
Тип 2:
при смешивании C и C++ (т. е. a. вызов функции C из C++; и b. вызов функции C++ из C), искажение имени C++ вызывает проблемы связывания. Технически говоря, эта проблема возникает только тогда, когда вызываемые функции уже скомпилированы в двоичный код (скорее всего, a *.файл библиотеки) с использованием соответствующего компилятора.
поэтому нам нужно использовать extern «C», чтобы отключить искажение имени в C++.
этот ответ для нетерпеливых / есть сроки, чтобы соответствовать, только часть / простое объяснение ниже:
Так
в C++ с именем mangling уникально идентифицирует каждую функцию
в C даже без искажения имени однозначно идентифицирует каждую функцию
чтобы изменить поведение C++, то есть указать это имя mangling не должен случается для определенной функции, вы можете использовать extern «C» перед именем функции, по какой-либо причине, например, экспорт функции с определенным именем из dll, для использования ее клиентами.
прочитайте другие ответы, для более подробных / более правильных ответов.
extern (C++)
extern Ключевое слово может быть применено к глобальной переменной, функции или объявлению шаблона. Он указывает, что символ имеет связь Al. Дополнительные сведения о компоновке и о том, почему не рекомендуется использовать глобальные переменные, см. в разделе Преобразование единиц и компоновки.
extern Ключевое слово имеет четыре значения в зависимости от контекста:
В const объявлении неглобальной переменной extern указывает, что переменная или функция определена в другой записи преобразования. extern Должен применяться ко всем файлам, за исключением того, где определена переменная.
В const объявлении переменной указывается, что переменная имеет extern связь Al. extern Должен применяться ко всем объявлениям во всех файлах. ( const По умолчанию глобальные переменные имеют внутреннюю компоновку.)
extern «C» Указывает, что функция определена в любом расположении и использует соглашение о вызовах на языке C. extern «C» Модификатор может также применяться к нескольким объявлениям функций в блоке.
extern компоновка для const неглобальных элементов
Если компоновщик видит extern перед объявлением глобальной переменной, он ищет определение в другой записи преобразования. Объявления const непеременных в глобальной области extern по умолчанию имеют значение Al. Применяется только extern к объявлениям, не предоставляющим определение.
extern компоновка для const глобальных элементов
const По умолчанию глобальная переменная имеет внутреннюю компоновку. Если требуется, чтобы переменная соимела extern связь Al, примените extern к определению ключевое слово и ко всем остальным объявлениям в других файлах:
extern constexpr компоновка
extern «C» и extern «C++»
В C++ при использовании со строкой extern указывает, что для деклараторов используются соглашения компоновки другого языка. Доступ к функциям и данным C можно получить только в том случае, если они были ранее объявлены с компоновкой C. Однако они должны быть определены в блоке трансляции, который компилируется отдельно.
Пример
В следующем примере показано, как объявить имена с компоновкой C:
Если у функции несколько спецификаций компоновки, они должны быть согласованы. Объявление функций как с помощью компоновки C, так и с + + является ошибкой. Кроме того, если два объявления для функции встречаются в программе, одна из которых имеет спецификацию компоновки, а другая — нет, объявление со спецификацией компоновки должно быть первым. Ко всем повторным объявлениям функций, уже имеющих спецификацию компоновки, применяется компоновка из первого объявления. Пример:
Польза от использования extern?
2 ответа 2
Этот вопрос в общем-то отвечен в документации и на форуме http://www.cplusplus.com/forum/general/21368/
Ключевое слово extern используется в трех случаях
Для описания статического хранилища со спецификатором внешнего связывания.
Для указания языка, «С» или «С++». Это влияет на то, происходит ли искажение имен для С++ или нет). Следует учитывать, что это не предполагает что код компилируется «как в Си».
extern template сlass-name ;
An explicit instantiation declaration (an extern template) skips implicit instantiation step: the code that would otherwise cause an implicit instantiation instead uses the explicit instantiation definition provided elsewhere (resulting in link errors if no such instantiation exists). This can be used to reduce compilation times by explicitly declaring a template instantiation in all but one of the source files using it, and explicitly defining it in the remaining file (С++11).
Декларация явной инстанциации шаблона (внешний шаблон) позволяет пропустить шаг неявного создания кода шаблона и вместо этого использовать экземпляр шаблона, описанный где-то еще (что привело бы к ошибкам редактора связей, если таковая не была произведена). В С++ декларация явной специализации во всех файлах исходных текстов кроме одного, где он будет определен полностью, может позволить сэкономить время компиляции.
Зачем нам нужен extern «C» <#include >в C ++?
Почему мы должны использовать:
В частности:
Когда мы должны использовать это?
Что происходит на уровне компилятора/компоновщика, что требует от нас его использования?
Как с точки зрения компиляции/компоновки это решает проблемы, которые требуют от нас его использования?
extern «C» определяет, как символы в сгенерированном объектном файле должны быть названы. Если функция объявлена без внешнего «C», имя символа в объектном файле будет использовать искажение имени C++. Вот пример.
Данный тест.С вроде так:
Компиляция и перечисление символов в объектном файле дает:
Функция foo фактически называется «_Z3foov». Эта строка содержит информацию о типе для возвращаемого типа и параметров, среди прочего. Если вы вместо этого напишите test.C, как это:
Затем скомпилируйте и посмотрите на символы:
Вы получаете связь C. Имя функции «foo» в объектном файле просто «foo», и в ней нет всей информации о причудливых типах, получаемой из искажения имени.
Большинство современных библиотек устанавливают защиту вокруг таких заголовков, чтобы символы объявлялись с правильной связью. например во многих стандартных заголовках вы найдете:
Это гарантирует, что когда код C++ включает заголовок, символы в вашем объектном файле совпадают с тем, что находится в библиотеке C. Вы должны только поместить extern «C» <> вокруг заголовка C, если он старый и у него нет этих охранников.
В C++ у вас могут быть разные сущности, которые имеют общее имя. Например, вот список функций с именами foo:
Чтобы различать их все, компилятор C++ создаст уникальные имена для каждого в процессе, называемом распределением имен или декорированием. Компиляторы C не делают этого. Кроме того, каждый компилятор C++ может делать это по-своему.
extern «C» говорит компилятору C++ не выполнять никакого искажения имени в коде в фигурных скобках. Это позволяет вам вызывать функции C из C++.
Это связано с тем, как разные компиляторы выполняют сортировку имен. Компилятор C++ будет манипулировать именем символа, экспортируемого из файла заголовка, совершенно иначе, чем компилятор C, поэтому, когда вы попытаетесь создать ссылку, вы получите сообщение об ошибке компоновщика, говорящее об отсутствии символов.
Чтобы решить эту проблему, мы говорим компилятору C++ работать в режиме «C», поэтому он выполняет преобразование имен так же, как и компилятор C. После этого исправлены ошибки компоновщика.
Когда мы должны использовать это?
Когда вы связываете библиотеки C в объектные файлы C++
Что происходит на уровне компилятора/компоновщика, что требует от нас его использования?
C и C++ используют разные схемы именования символов. Это говорит компоновщику использовать схему C при компоновке в данной библиотеке.
Как с точки зрения компиляции/компоновки это решает проблемы, которые требуют от нас его использования?
Использование схемы именования C позволяет ссылаться на символы стиля C. В противном случае компоновщик будет использовать символы стиля C++, которые не будут работать.
Линкеры были созданы для C и других языков, таких как C, с этим простым правилом именования символов. Таким образом, символы в компоновщике являются просто строками.
Но в C++ язык позволяет вам иметь пространства имен, полиморфизм и другие вещи, которые противоречат такому простому правилу. Все шесть ваших полиморфных функций, называемых «add», должны иметь разные символы, иначе неправильная будет использоваться другими объектными файлами. Это делается путем «искажения» (это технический термин) имен символов.
При связывании кода C++ с библиотеками C или кодом, вам нужно extern «C» что-нибудь написанное на C, например заголовочные файлы для библиотек C, чтобы сообщить компилятору C++, что эти имена символов не должны быть искажены, в то время как остальные Ваш код C++, конечно, должен быть искажен, иначе он не будет работать.
Компилятор C++ создает имена символов иначе, чем компилятор C. Итак, если вы пытаетесь вызвать функцию, которая находится в C-файле, скомпилированном в C-код, вам нужно сообщить компилятору C++, что имена символов, которые он пытается разрешить, выглядят не так, как по умолчанию; в противном случае шаг ссылки потерпит неудачу.
Вы должны использовать extern «C» в любое время, когда вы включаете функции определения заголовка, находящиеся в файле, скомпилированном компилятором C, который используется в файле C++. (Многие стандартные библиотеки C могут включать эту проверку в свои заголовки, чтобы сделать ее проще для разработчика)
Использование extern «C» решает вышеуказанную проблему, сообщая компилятору C++, что он должен искать функцию, которая следует соглашению об именовании C вместо C++.
Конструкция extern «C» <> указывает компилятору не выполнять искажение имен, объявленных в фигурных скобках. Обычно компилятор C++ «улучшает» имена функций, чтобы они кодировали информацию о типе аргументов и возвращаемого значения; это называется искаженное имя. Конструкция extern «C» предотвращает искажение.
Обычно используется, когда код C++ должен вызывать библиотеку языка C. Это также может быть использовано при предоставлении функции C++ (например, из DLL) клиентам C.
Это используется для решения проблем искажения имен. extern C означает, что функции находятся в «плоском» C-стиле API.