Подтвердить что ты не робот

Какие проблемы я могу ожидать, компилируя C-код с помощью компилятора С++?

Если вы берете существующую базу кода C и компилируете ее с помощью компилятора С++, какие проблемы вы можете ожидать? Например, я думаю, что присвоение целочисленного значения значению с перечисляемым типом не будет выполняться в С++, тогда как оно законно (если немного противно) в C.

Если я не буду обертывать все мои файлы C в extern C { ... }, я собираюсь получить управление именами, где я меньше всего этого ожидаю? Есть ли причина, почему я действительно не должен этого делать?

Для фона у нас очень большая база кода, написанная на C. В течение нескольких лет мы прыгали через обручи, чтобы делать что-то, что могло бы произойти, естественно, через С++ (наследование homebrewe, например). Мы хотели бы начать двигаться к С++, но постепенно; получение нашей CORBA-подобной структуры для ее поддержки и рефакторинг модулей по мере продвижения вперед, чтобы воспользоваться более естественным подходом С++.

4b9b3361

Ответ 1

Я однажды сделал что-то подобное. Основным источником проблем было то, что С++ более строго относится к типам, как вы подозревали. Вам придется добавлять отливки, где void * смешиваются с указателями других типов. Подобно распределению памяти:

Foo *foo;
foo = malloc(sizeof(*foo));

Вышеприведенный типичный C-код, но для С++ он нужен:

Foo *foo;
foo = (Foo*)malloc(sizeof(*foo));

В С++ есть новые зарезервированные слова, такие как "class", "and", "bool", "catch", "delete", "explicit", "mutable", "namespace", "new", оператор "," или ", "private"," защищенный "," друг "и т.д. Они не могут использоваться, например, как имена переменных.

Вышеупомянутые, вероятно, являются наиболее распространенными проблемами при компиляции старого кода C с помощью компилятора С++. Полный список несовместимостей см. В Несовместимость между ISO C и ISO С++.

Вы также спрашиваете о mangling имени. В отсутствие внешних оболочек "C" компилятор С++ будет калечить символы. Это не проблема, если вы используете только компилятор С++ и не полагаетесь на dlsym() или что-то в этом роде, чтобы вытаскивать символы из библиотек.

Ответ 2

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

// In C, prints 4.  In C++, prints 1
printf("%d\n", sizeof('A'));

Ответ 3

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

Он кусает вас, когда вы пытаетесь связать C и С++.

Я написал много файлов заголовков, содержащих:

#ifdef __cplusplus
    extern "C" {
#endif

// rest of file

#ifdef __cplusplus
    }
#endif

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

Есть ли какая-то причина, почему я действительно не должен этого делать?

Если вы точно знаете, что не собираетесь комбинировать C и С++, тогда нет оснований для этого, о котором я знаю. Но с постепенной миграцией, которую вы описываете, это важно для чего-либо с опубликованным интерфейсом, который должны использовать как компоненты C, так и компоненты С++.

Большая причина не в том, что это не позволяет вам перегружать функции (по крайней мере, в этих заголовках). Возможно, вы захотите сделать это, как только вы перенесили весь свой код на С++ и начали поддерживать/рефакторинг/расширение.

Ответ 4

Еще один пример: не существует неявного преобразования из ints в enums в С++, тогда как в C вам понадобится листинг, если вы действительно хотите сделать это на С++.

Ответ 5

Я сделал это до использования MSVC, если вы используете MSVC, хорошая стратегия:

  • Задайте отдельные файлы для сборки как CPP, таким образом вы можете постепенно переходить к компилятору CPP.
  • Работайте с файлом с помощью ctrl + f7 только для создания этого файла.
  • Вместо того, чтобы бросать все маллоки, вы можете создать версию шаблона вместо

foo = (Foo *) malloc (sizeof (* foo));

становится

foo = malloc<Foo>();

И, конечно, у вас может быть перегрузка для случаев, когда вы хотите Foo + n байтов

Я бы также пересмотрел распределение памяти для использования RAII, где это возможно, я обнаружил, что некоторые функции, где довольно сложно, поэтому переход на RAII был слишком высоким, в большинстве случаев это было достаточно просто сделать.

Ответ 6

У С++ более строгая проверка типов, поэтому вам может потребоваться добавить приведение к каждому вызову в malloc/realloc/calloc.

Ответ 7

В общем, у вас не будет никаких проблем. Да, есть некоторые несовместимости между C и С++, но они, похоже, не так часто возникают, за исключением упомянутого выше литья malloc, что довольно тривиально для исправления.

Я успешно скомпилировал и использовал следующие библиотеки C с открытым кодом С++:

  • парсер Expat XML
  • Растеризатор шрифтов FreeType2
  • libjpeg: обрабатывает изображения JPEG
  • libpng: обрабатывает изображения PNG
  • библиотека сжатия Zlib

Самая сложная часть заключалась в добавлении оболочек пространства имен, что заняло несколько часов, в основном из-за операторов #include, глубоко погруженных в код, которые должны были находиться за пределами пространства имен С++.

Почему я это сделал? Потому что я продаю коммерческую библиотеку, которую люди связывали напрямую в свои приложения; и иногда их приложения были связаны с другими версиями Expat, FreeType и т.д. Это вызвало ошибки с несколькими символами. Самое лучшее, что нужно сделать, это переместить все в мою библиотеку и скрыть ее в моем пространстве имен.

Однако я не делал этого со всеми библиотеками с открытым исходным кодом, которые я использую. Некоторые из них еще не вызвали конфликтов, и я не стал их исправлять, что, несмотря на отсутствие проблем, довольно утомительно. Интересным исключением является SQLite, который я не смог скомпилировать на С++. Поэтому я сделал массивный поиск и заменил, добавив префикс (имя моего продукта) к каждому видимому извне символу. Это решило мою проблему с клиентом.

Ответ 8

попробуйте выполнить компиляцию с помощью компилятора С++:

typedef enum{ false = 0, true = 1} bool;