21

現在、C で 32 ビット アプリケーションを 64 ビット アプリケーションに変換する作業を行っています。このアプリケーションは、現在 x86 アーキテクチャ (Windows、osx、Unix、Linux) で作業しています。そのため、コーディングを開始する前に、アプリケーションを変換する際に何を考慮する必要があるかを知りたいと思いました。

4

8 に答える 8

29
  1. 誰が書いたのか調べてください。彼らはばかですか?彼らは数年前からですか彼らに質問できますか?複数のプラットフォームやシステムの存在に精通していますか? プログラムの作成者の考え方を知ることは、問題に遭遇したときに問題を理解するのに役立ちます。
  2. 64 ビット マシン/ビルド環境を起動して実行します。
  3. long を int に置き換えます。LONGではないことを十分に認識してくださいlong
  4. (int)&xキャストと入力をintptr_tand(unsigned int)&xで置き換えますuintptr_t
  5. char*ポインター演算を行うために構造体のキャストに依存するものはすべて監査します。
  6. \<4\> の正規表現検索4 = sizeof(void*)
  7. 我慢して。問題が見つかったら、同じ問題が存在する場合は別の場所を調べ、解決策をマクロにラップします。
  8. または類似のものを使用しないようにしてください#ifdef RUN64。128 ビット プラットフォームが流行したら後悔するでしょう。
  9. プログラムの他の場所での移植性の違いを隠すいくつかの集中型マクロに関して、すべての変更をカプセル化します。
  10. カバレッジ テスターを使用して、すべてをカバーしていることを確認します (該当する場合)。

uintptr_tコメントで提案されているように編集してメモを追加しました。

于 2009-01-04T22:35:10.907 に答える
9

まだ言及されていない潜在的な問題の1つは、アプリがディスクからバイナリデータを読み書きする場合(たとえば、を使用して構造体の配列を読み取る場合fread)、非常に注意深くチェックする必要があり、おそらく2つのリーダーが必要になることです。1つはレガシーファイル用です。 1つは64ビットファイル用です。uint32_tまたは、ヘッダーファイルのなどのタイプを注意深く使用する場合は<stdint.h>、構造体をビットごとに互換性があるように再定義できます。いずれにせよ、バイナリI/Oは注意が必要です。

于 2009-01-04T22:49:10.083 に答える
6

これは、アプリケーションとそのコーディング方法に大きく依存します。一部のコードは 64 ビット コンパイラで再コンパイルするだけで機能しますが、通常、これはコードが移植性を考慮して設計されている場合にのみ発生します。

コードにネイティブ型とポインタのサイズに関する多くの仮定がある場合、ビット パッキング ハックが多くある場合、またはバイト指定のプロトコルを使用して外部プロセスと通信するが、ネイティブ型のサイズに関するいくつかの仮定を使用している場合クリーンなコンパイルを行うには、ある程度の、または多くの作業が必要になる場合があります。

ほとんどすべてのキャストとコンパイラの警告は、チェックアウトが必要な危険信号です。コードが最初から「クリーンな警告」をしていなかった場合、それは多くの作業が必要になる可能性があることを示しています。

于 2009-01-04T22:33:17.980 に答える
5

値に正しいタイプを使用した場合-たとえば。size_tptrdiff_t、 、適切な場所uintptr_tからの固定サイズの int 型- 値のサイズをハードコードしていない場合、コードはそのまま使用できるはずです。stdint.h

于 2009-01-04T22:30:27.907 に答える
4

Cでの32ビットプログラミングと64ビットプログラミングの2つの大きな違いはsizeof(void*)、とsizeof(long)です。発生する主な問題は、ほとんどのUnixシステムが64ビットを定義するI32LP64標準を使用し、Win64が32ビットを定義するIL32LLP64標準を使用することです。クロスプラットフォームコンパイルをサポートする必要がある場合は、32ビットおよび64ビット整数のアーキテクチャベースのtypedefのセットを使用して、すべてのコードが一貫して動作するようにすることができます。これは、C99標準の一部としてstdint.hの一部として提供されます。C99コンパイラを使用していない場合は、独自の同等のコンパイラをロールする必要がある場合があります

sizeof(int) == sizeof(long) == sizeof(void*)他の場所で述べたように、変換の主な懸念事項は、ディスクに書き込まれたデータをサポートするコードとクロスプラットフォームIPCのコードを想定したコードです。

この背後にある歴史の良いレビューについては、ACMキューからのこの記事を見てください。

于 2009-01-05T04:50:32.477 に答える
3

64 ビットに切り替えるときに直面する主な問題は、ポインターのサイズが異なることです (32 ビットではなく 64 ビット - 当然) プラットフォームによっては、整数のサイズと long のサイズも異なる場合があります。

なぜこれが問題なのですか?コードで sizeof(int) == sizeof(void*) と想定されていない限り、そうではありません。これは厄介なポインターのバグにつながる可能性があります。

于 2009-01-04T22:31:12.053 に答える
3

基本的に、変更の数はかなり少ないですが、アプリケーションが最初からある程度移植可能になるように注意深く作成されていなければ、依然として大きな作業になります。

主な違いは、ポインターが 64 ビット幅であることです、他のほとんどのデータ型は変更されていません。int はまだ 32 ビットであり、long もおそらくまだ 32 ビットです。そのため、コードが int とポインタの間でキャストすると、それが壊れます。同様に、メンバーへの特定のオフセットに依存する構造体などは、他のメンバーが大きくなり、オフセットが変更される可能性があるため、破損する可能性があります。

もちろん、コードは最初からこれらのトリックに依存するべきではありません。したがって、理想的な世界では、これはまったく問題にならず、単純に再コンパイルするだけですべてが機能します。しかし、あなたはおそらく理想的な世界に住んでいないでしょう... ;)

于 2009-01-04T22:36:18.050 に答える
2

すでに多くの良い答えがあります。

Gimpel Lintの使用を検討してください。問題のある構造のタイプを正確に指摘できます。あなたの経験が私のようなものであれば、32/64 ビット ポートとは関係のないシステムの多くのバグも表示されます。

于 2009-01-05T11:22:31.077 に答える