3

Visual C/C++ 2005/2008 で記述されたプログラムは、GNU C/C++ などの別のコンパイラではコンパイルできない場合があり、その逆も同様です。たとえば、特定のコンパイラ用に書かれた windows.h を使用するコードを別のコンパイラで再利用しようとする場合、注意すべき違いは何ですか?

GC/C++ または MSVC/C++ など、あるコンパイラまたは別のコンパイラと互換性のあるコードを生成する方法に関する情報はありますか? これを行おうとすると、どのような問題が発生しますか?

LCC や Digital Mars などの他のコンパイラはどうですか?

4

7 に答える 7

7

MSVC用に記述されたコードを他のコンパイラにコンパイルしようとするときに最初に行うことは、Microsoft拡張機能をオフにしてコンパイルすることです。(/ Zaフラグを使用すると思います)。それはGCCや他のコンパイラが不平を言うであろう多くのことを吸い取るでしょう。

次のステップは、Windows固有のAPI(MFC、Win32など)がWindows固有のファイルに分離されていることを確認し、コードを「汎用」モジュールと「Windows固有」モジュールに効果的に分割することです。

于 2008-11-17T10:25:42.243 に答える
5

Web ページをさまざまなブラウザーで動作させたい場合は、標準に準拠した HTML を作成する必要があるという議論を覚えていますか?

コンパイラも同様です。

言語レベルでは、コードが -std=c89 (または C++ の場合は -std=c++98) を使用して GCC で警告なしにコンパイルされる場合、-pedantic -Wall に加えて、勇気がある場合は -Wextra を使用します。 -pedantic で許可されている露骨な GNU 拡張機能 (誤って行うのは難しい) を使用していない場合は、ほとんどの C89 コンパイラで動作する可能性が高くなります。C++ は、ターゲット コンパイラのサポートが標準に対してどれだけ完全であるかに依存している可能性があるため、少し確実ではありません。

正しい C89 の記述は多少制限があります ( // コメント、宣言はブロック内のステートメントの前に置く必要がある、インライン キーワードがない、stdint.h がないため 64 ビット型がないなど) が、慣れればそれほど悪くはありません。GCC と MSVC だけに関心がある場合は、MSVC にあるとわかっているいくつかの言語機能を有効にすることができます。それ以外の場合は、独自の小さな「言語抽象化」ヘッダーを作成できます。たとえば、GCC と MSVC/C++ では「inline」を「inline」と定義し、MSVC/C では「__inline」と定義します。または、MSVC stdint.h は簡単に見つけたり書き込んだりできます。

私は過去に移植可能なコードを書いたことがあります.GCCを使用して、特定の製品の1つのプラットフォームで主に作業していました。また、Windows XP やモバイルなど、すべてのプラットフォームで使用できるコードも作成しました。ビルド サーバーで「テスト ビルド」を実行する前に、これらのプラットフォーム用にコンパイルしたことは一度もありませんでした。問題が発生することはほとんどありませんでした。1 回か 2 回、64 ビットの互換性に関する警告が表示される悪いコードを書いた可能性があります。

Windows プログラマーが別の方向に進んでいると、時折問題が発生しました。その主な理由は、彼らのコンパイラーが私たちのコンパイラーよりも衒学的でなかったためです。そのため、GCC がまったくサポートしていないものではなく、彼らがしていない警告が表示されました。しかし、警告を修正したということは、コードが後でより原始的なコンパイラを備えたシステムで使用されたときに、まだ機能していたことを意味していました。

ライブラリレベルでは、はるかに困難です。windows.h 経由で Wi​​ndows API を #include して使用すると、明らかに Linux では動作しません。GCC で KDE を使用し、MSVC でコンパイルしようとしても同じです。

厳密に言えば、これはプラットフォームの問題であり、コンパイラの問題ではありませんが、同じことになります。移植可能なコードを書きたい場合は、すべてのターゲットがサポートする POSIX (またはそのサブセット) などの OS 抽象化 API が必要であり、最初にそれを記述するときに「移植可能」であると考える必要があります。Windows 固有の API を多用するコードを取得し、それを GCC/Linux で動作させようとすることは、基本的に AFIAK を完全に書き直すことです。再コンパイルを試みるよりも、WINE を使用した方がよい場合があります。

于 2008-11-17T16:02:27.523 に答える
5

「コンパイラ」と「OS」を混同しています。<windows.h> は、MSVC C コンパイラが提供するものではありません。Windows API の C 固有の実施形態です。Visual Studio から独立して取得できます。Windows 上の他の C コンパイラは、それを提供する可能性があります。たとえば、Linux 側では、<unistd.h>、<pthereads.h> などがあります。これらは GCC の重要な部分ではなく、Linux 用にコンパイルする他のコンパイラはそれらを提供します。

したがって、2 つの異なる質問に答える必要があります。どのコンパイラでも受け入れられるように C をコーディングするにはどうすればよいでしょうか? また、OS への依存関係を非表示にするにはどうすればよいですか?

于 2008-11-17T17:09:10.743 に答える
5

さまざまな回答からわかるように、このトピックはかなり複雑です。ここで、3 つのプラットフォーム (msvc 8/Windows、gcc 4.2/Linux、gcc 3.4/embedded 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 はこの点で緩いです (特定のコンパイラ スイッチが警告を生成したと思いますが)。数か所に追加する必要がありました。

c) 単純だが時間がかかる: Windows では大文字と小文字が区別されず、多くの #include ファイルが大文字と小文字を正しく指定せずに指定され、Linux で問題が発生しました。

d) 多くの目的で Windows API を使用するかなりの量のコードがありました。CRITICAL_SECTIONS と INTERLOCKED_INCREMENT の例です。これらの問題を置き換えるためにできる限りブースト ライブラリを使用しましたが、コードの修正には時間がかかります。

e) コードの多くは、プリコンパイル済みヘッダーに含まれるヘッダーに依存していました。gcc3.4 で pch を使用する際に問題が発生したため、すべての .h/cpp ファイルにすべての依存関係が正しく含まれていることを確認する必要がありました (最初に含まれている必要があります)。

f) VS 2005 には厄介なバグが 2 つあります。 auto_ptr は何にでも割り当てることができ、一時変数は参照パラメーターに渡すことができます。どちらも (ありがたいことに!) gcc ではコンパイルに失敗しますが、やり直しが必要です。

g) 奇妙なことに、クラステンプレート関数を明示的に特殊化しようとするテンプレート コードがありました。禁止されている。再び gcc は拒否し、VS 2005 はそれを手放しました。問題が理解されれば、通常のオーバーロードに簡単に作り直すことができます。

h) VS 2005 では、std::exception を文字列で構築できます。gcc または標準では許可されていません。派生例外クラスのいずれかを使用するようにコードを修正します。

うまくいけば、それはあなたが探していた種類の情報です!

于 2008-11-18T07:16:50.563 に答える
4

うーん、これはかなり難しい質問です。事実、MSVC は最新の C 標準をサポートしていません。C++ への準拠については、何でも教えていただけます。ただし、「windows」C は MSVC と gcc の両方で理解されており、他の方法を期待することはできません。たとえば、ANSI C99 機能を使用している場合、gcc から MSVC への「移植」に苦労する可能性があります。

しかし、MSVC-> gcc の方法を試す限り、可能性は高くなります。注意しなければならないのはライブラリだけです。Windows のライブラリのほとんどは MSVC で動作することになっているため、gcc からもアクセスできるようにするには、追加のツールが必要です。

LCC はかなり古いシステムであり、AFAIKT は ANSI C99 からあまりサポートしていません。適切に動作するには MSVC のツールも必要です。LCC は「単なる」コンパイラです。

lcc-win32 は、ANSI C99 準拠を目指す C 開発システムです。リンカー、IDE などが付属しています。

Digital Marsの実装状況についてはなんとも言えません

次に、本格的な IDE である Pelles-C もあります。

そして、私たちは OpenWatcom をぶらぶらしています。これはかつてはかなりまともなシステムでしたが、それがどれほど適合しているかはわかりません.

全体として、MSVC -> 他のシステムからのより簡単な方法を期待できる「最良の」方法ですが、おそらくその逆の方がはるかに悪いでしょう。

よろしく フリードリヒ

于 2008-11-17T09:31:19.233 に答える
1

Visual C/C++ 2005/2008 で記述されたプログラムは、GNU C/C++ などの別のコンパイラではコンパイルできない場合があり、その逆も同様です。

これは、次のいずれかの場合に当てはまります (1) あるコンパイラでは利用できるが、別のコンパイラでは利用できないある種の拡張機能を使用します (たとえば、C++ 標準ではいくつかの場所でtypenameandtemplateキーワードが必要ですが、Visual C++ を含む多くのコンパイラではこれが強制されません。 gcc は以前はこれを強制していませんでしたが、3.4 で変更されました) または (2) あるコンパイラでは実装されているが別のコンパイラでは実装されていない標準準拠の動作を使用します (現在、これのポスターボーイはエクスポートされたテンプレートですが、これをサポートするコンパイラは 1 つまたは 2 つだけです。 Visual C++ と gcc はそのグループに含まれません)。

たとえば、特定のコンパイラ用に書かれた windows.h を使用するコードを別のコンパイラで再利用しようとすると、

これを行うのに問題があるのを見たことがありません。gcc で Microsoft の windows.h を使用すると問題が発生します。しかし、gcc で gcc の windows.h を使用し、Visual C++ で Microsoft の windows.h を使用すると、文書化されているすべての関数にアクセスできます。結局のところ、それが「実装されたwindows.h」の定義です。

知っておくべき違いは何ですか?

私が見た主なものは、上記の依存template/事について知らない人々です。typename多くの人が gcc は Visual C++ と同じようにスマートではないと考えているのはおかしいと思いますが、実際には gcc に最初に機能があり、その後標準準拠の名目でそれを削除することにしました。

近い将来、C++0x 機能を使用すると問題が発生するでしょう。しかし、gcc と Visual C++ の両方が、その標準でより簡単なものを実装しています。

于 2008-11-17T19:16:37.040 に答える
1

vs2008 は 2005 よりもはるかに多くの標準に準拠し
ています。特に、実行時に可変サイズの配列を割り当てることができる gcc の「機能」「int array[variable]」は、逆に多くの問題を抱えていました。悪の権化。

于 2008-12-12T17:45:29.900 に答える