Каковы практические различия между компиляторами C в Windows? - PullRequest
3 голосов
/ 17 ноября 2008

Программа, написанная на Visual C / C ++ 2005/2008, может не компилироваться с другим компилятором, таким как GNU C / C ++ или наоборот. Например, при попытке повторного использования кода, который использует windows.h, написанный для конкретного компилятора, с другим, какие различия следует знать?

Есть ли какая-либо информация о том, как создать код, совместимый с тем или иным компилятором, например, с GC / C ++ или MSVC / C ++? Какие проблемы будут пытаться сделать это причиной?

А как насчет других компиляторов, таких как LCC и Digital Mars?

Ответы [ 7 ]

7 голосов
/ 17 ноября 2008

Первое, что нужно сделать при попытке скомпилировать код, написанный для MSVC, в другие компиляторы, это скомпилировать его с отключенными расширениями Microsoft. (Используйте флаг / Za, я думаю). Это выкурит много вещей, на которые GCC и другие компиляторы будут жаловаться.

Следующим шагом является обеспечение того, чтобы специфичные для Windows API (MFC, Win32 и т. Д.) Были изолированы в специфичных для Windows файлах, эффективно разделяя ваш код на «общие» и «специфичные для Windows» модули.

5 голосов
/ 18 ноября 2008

Как вы можете судить по разным ответам, эта тема довольно сложная. Имея это в виду, вот некоторые проблемы, с которыми я столкнулся, когда недавно портировал код для трех платформ (msvc 8 / Windows, gcc 4.2 / Linux, gcc 3.4 / встроенный процессор ARM9). Первоначально он компилировался только под Visual Studio 2005.

a) Большая часть кода, написанного на платформах Windows, использует типы, определенные в windows.h. Мне пришлось создать файл "windows_types.h" со следующим:

#ifndef _WIN32
    typedef short              INT16;
    typedef unsigned short     UINT16;
    typedef int                INT32;
    typedef unsigned int       UINT32;
    typedef unsigned char      UCHAR;
    typedef unsigned long long UINT64;
    typedef long long          INT64;
    typedef unsigned char      BYTE;
    typedef unsigned short     WORD;
    typedef unsigned long      DWORD;
    typedef void *             HANDLE;
    typedef long               LONG;
#endif

Ужасно, но гораздо проще, чем модифицировать код, который ранее был предназначен только для Windows.

b) Ключевое слово typename не требовалось в шаблонном коде для объявления типов. MSVC слабо в этом отношении (хотя я предполагаю, что некоторые ключи компилятора сгенерировали бы предупреждение). Пришлось добавить его в нескольких местах.

в) Простой, но трудоемкий: Windows не чувствительна к регистру, и многие #include файлы были указаны с неправильным регистром, вызывая проблемы в Linux.

d) Было много кода, использующего Windows API для многих вещей. Пример был для CRITICAL_SECTIONS и INTERLOCKED_INCREMENT. Мы использовали как можно больше библиотек надстроек, чтобы заменить эти проблемы, но переработка кода отнимает много времени.

e) Большая часть кода основывалась на включении заголовков в предварительно скомпилированные заголовки. У нас были проблемы с использованием pch на gcc3.4, поэтому мы должны были убедиться, что все файлы .h / cpp правильно включали все их зависимости (как они должны были в первую очередь).

е) VS 2005 имеет две неприятные ошибки. auto_ptr можно присвоить чему угодно , и временные переменные могут быть переданы в ссылочные параметры. Оба не компилируются (к счастью!) Под gcc, но требуется доработка.

g) Странно, у нас был шаблонный код, который пытался явно специализировать шаблонные функции class . Не положено. Опять gcc отказался, VS 2005 отпустил. Достаточно легко преобразовать в обычные перегрузки, как только проблема понята.

h) В соответствии с VS 2005 std :: exception разрешено создавать со строкой. Не допускается в соответствии с GCC или стандартом. Переработайте свой код, чтобы он предпочел использовать один из производных классов исключений.

Надеюсь, именно такую ​​информацию вы искали!

5 голосов
/ 17 ноября 2008

Вы смешиваете "компиляторы" и "ОС". - это не то, что компилятор MSVC C вносит в таблицу: это специфичное для C воплощение Windows API. Вы можете получить его независимо от Visual Studio. Любой другой компилятор C в Windows, вероятно, предоставит его. Например, на стороне Linux у вас есть , и другие. Они не являются неотъемлемой частью GCC, и любой другой компилятор, который компилируется для Linux, предоставит их.

Итак, вам нужно ответить на два разных вопроса: как я могу кодировать C таким образом, чтобы его принимал любой компилятор? И как мне скрыть свои зависимости от ОС?

5 голосов
/ 17 ноября 2008

Помните аргумент, что если вы хотите, чтобы ваша веб-страница работала в разных браузерах, то вы должны писать HTML-совместимый стандарт?

То же самое касается компиляторов.

На уровне языка, если ваш код компилируется без предупреждений в GCC с -std = c89 (или -std = c ++ 98 для C ++), -pedantic -Wall, плюс -Wextra, если вы чувствуете себя смелым, и до тех пор, пока вы не использовали ни одно из более явных расширений GNU, разрешенных -pedantic (что трудно сделать случайно), у него есть хорошие шансы работать на большинстве компиляторов C89. C ++ немного менее определен, поскольку вы потенциально полагаетесь на то, насколько полной поддержка целевого компилятора для стандарта.

Написание правильного C89 несколько ограничительно (никакие // комментарии, объявления не должны предшествовать операторам в блоке, никакое встроенное ключевое слово, никакой stdint.h и, следовательно, никаких 64-битных типов и т. Д.), Но это не так уж плохо, как только вы привыкнете Это. Если вам важны только GCC и MSVC, вы можете включить некоторые языковые функции, которые, как вам известно, есть в MSVC. В противном случае вы можете написать свои собственные «языковые абстракции». Например, тот, который определяет «inline» как «inline» в GCC и MSVC / C ++, но «__inline» для MSVC / C. Или MSVC stdint.h достаточно легко найти или написать.

В прошлом я успешно писал переносимый код - я работал в основном на одной платформе для конкретного продукта, используя GCC. Я также написал код для использования на всех платформах, включая Windows XP и Mobile. Я никогда не компилировал его для этих платформ до запуска «тестовой сборки» на сервере сборки, и у меня очень редко возникали проблемы. Я думаю, что мог написать плохой код, который вызвал предупреждение о совместимости 64-битной версии один или два раза.

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

На уровне библиотеки это намного сложнее. Если вы #include и используете Windows API через windows.h, то, очевидно, это не сработает на Linux, и то же самое, если вы используете KDE с GCC, а затем пытаетесь скомпилировать с MSVC.

Строго говоря, это проблема платформы, а не проблема компилятора, но это то же самое. Если вы хотите написать переносимый код, вам нужен API абстракции ОС, такой как POSIX (или его подмножество), который поддерживают все ваши цели, и вам нужно думать о «переносимости», когда вы пишете его в первую очередь. Взятие кода, интенсивно использующего API для Windows, и попытка заставить его работать в GCC / Linux - это, по сути, полное переписывание AFIAK. Возможно, вам лучше использовать WINE, чем пытаться пересобрать его.

4 голосов
/ 17 ноября 2008

Ну, это довольно сложный вопрос. Дело в том, что MSVC не поддерживает новейшие Стандарт C, о соответствии c ++, я могу сказать вам все. Однако "Windows" C понимает MSVC и GCC, вы просто не можете надеяться на другой путь. Например, если вы используете функции ANSI C99, вам, возможно, будет нелегко «портировать» с gcc на MSVC.

Но если вы попробуете способ MSVC-> gcc, ваши шансы будут лучше. Единственный момент, о котором вы должны знать, это библиотеки. Предполагается, что большинство библиотек в Windows работают с MSVC, поэтому вам нужны дополнительные инструменты, чтобы сделать их также доступными для gcc.

LCC - довольно старая система, которую AFAIKT не очень поддерживает из ANSI C99, для правильной работы ей также нужны инструменты от MSVC. LCC "просто" компилятор.

lcc-win32 - это система разработки C, которая стремится соответствовать ANSI C99. Он поставляется вместе с компоновщиком, IDE и т. Д.

Не могу рассказать о состоянии внедрения Digital Mars

Затем существует Pelles-C, который также является полноценной IDE.

И у нас висит вокруг OpenWatcom. Который когда-то был довольно приличной системой, но я не могу сказать, насколько она соответствует.

В целом, «лучшее» можно надеяться на более легкий путь от MSVC -> другой системы, но, скорее всего, будет гораздо хуже.

С уважением Friedrich

1 голос
/ 12 декабря 2008

по сравнению с 2008 годом намного более соответствует стандартам, чем 2005.
У меня было больше проблем, идущих в другую сторону, особенно «особенность» gcc, которая позволяет вам выделять массив с переменным размером во время выполнения «int array [variable]», который является просто чистым злом.

1 голос
/ 17 ноября 2008

Программа, написанная на Visual C / C ++ 2005/2008, может не компилироваться с другим компилятором, таким как GNU C / C ++ или наоборот.

Это верно, если вы либо (1) используете какое-то расширение, доступное в одном компиляторе, но не в другом (например, стандарт C ++ требует ключевых слов typename и template в нескольких местах, но во многих компиляторах - в том числе Visual C ++ этого не применяют, gcc раньше тоже этого не применял, но изменен в 3.4 ) или (2) использует некоторое стандартное совместимое поведение, реализованное в одном компиляторе, но не в другом (прямо сейчас мальчик постера) это экспортируемые шаблоны, но только один или два компилятора поддерживают это, и Visual C ++ и gcc не входят в эту группу).

Например, при попытке повторного использования кода, который использует windows.h, написанный для определенного компилятора с другим,

Я никогда не видел проблемы с этим. Я видел проблему с использованием Microsoft Windows.h в GCC. Но когда я использую gcc windows.h в gcc и Microsoft windows.h в Visual C ++, я имею доступ ко всем документированным функциям. В конце концов, это определения "реализованного windows.h".

Какие различия следует знать?

Главное, что я видел, это люди, не знающие о упомянутой выше зависимости template / typename. Мне показалось забавным, что многие люди думают, что gcc недостаточно умен, чтобы делать то, что делает Visual C ++, когда в действительности у gcc была функция, а затем решили удалить ее во имя соответствия стандартам.

В ближайшее время у вас возникнут проблемы с использованием функций C ++ 0x. Но и gcc, и Visual C ++ реализовали более простые вещи в этом стандарте.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...