web-dev-qa-db-ja.com

解決方法:Cコードの「異なるサイズの整数からポインターへのキャスト」警告?

レガシーコードからgcc警告を削除しています。

型キャストを使用して、「異なるサイズの整数からポインタへのキャスト」という警告を抑制することは可能ですか?

example:

some_struct *ptr = func()  // func() returns an integer.

誰かがそのようなgcc警告を解決する方法を教えてくれますか?

10
Sandeep Singh

まず、func(ソースの変更が許可されている)を修正できる場合は、修正します。その計算がポインターで実行できる場合は、ポインターで実行してポインターを返します。時々、アドレスを整数として処理する正当な理由があります(たとえば、特別なコードでアライメントの問題を処理するなど)。その場合、_funcを変更して、uintptr_tタイプ(stdint.hで定義)を使用します。必要に応じてポインタを整数として扱うように設計されています。 (何らかの理由で符号付き算術の方が良い場合はintptr_tもありますが、通常、符号なしuintptr_tの方が問題が少ないと思います。)funcは、返すときにuintptr_tをポインタに変換する必要があるため、戻り値の型of funcはポインタになります(おそらくsome_structまたはvoidへのポインタ)。

funcを修正できない場合は、キャストを使用して、実行中の変換を行うつもりであることをコンパイラーに通知できます。ただし、この特定のエラーメッセージは、整数をポインターに変換するだけでなく、あるサイズ(たとえば、4バイト)の整数を別のサイズ(たとえば、8バイト)のポインターに変換することを示しています。このコードは、funcによって返される整数型がポインタ型と同じサイズであるシステム用に最初に書かれた可能性がありますが、現在、ポインタ型がそれよりも大きいまたは小さいシステムでコンパイルしています整数サイズ。

その場合、funcによって実行される計算が新しいアーキテクチャで機能することを確認する必要があります。 32ビット値のみを返す場合、常に正しい値が保持されますか?つまり、欠落している上位32ビットによって何も失われませんか? funcが計算する必要のあるアドレスは、使用する整数型の最大値を超えませんか? funcが符号付き整数型を使用している場合は、符号ビットも検討してください。

funcによって返される値が正しいことを確認したら、some_struct *ptr = (some_struct *) (intptr_t) func();などの明示的なキャストを使用できます。

21

私のgccはあなたが引用した警告を出しません。コードにキャストがないため、これも奇妙です。

警告が出ます

_assignment makes pointer from integer without a cast
_

「キャストなし」の部分に注意してください。したがって、(動作を変更せずに)キャストすることでgccをサイレントにすることができます。

_some_struct *ptr = (void*)func();
_

次に、funcの戻り値の型がアドレスに適合しない場合、警告(「異なるサイズの整数からのポインターへのキャスト」)が表示されます。これは、func()を適切な整数型に追加でキャストすることで沈黙させることができます。 _intptr_t_:

_some_struct *ptr = (void*)(intptr_t)func();
_

これはすべて、実際に間違ったサイズの整数をポインターに変換したいという仮定の下にあります。おそらく、コードを作り直す方が良いでしょう。

6
undur_gongor

ここには2つの可能性があります。

  1. funcが実際のポインターを整数にキャストしています。後でポインタとして使用されます。
  2. funcは、ポインターに格納されている整数を返します。 ptrは後で整数にキャストされ、整数として使用されます。

最初のケースでは、funcからの戻り値は情報を失いintがデータポインターのサイズよりも小さい場合、クラッシュまたはさらに悪い可能性があります。ほとんどの 64ビットメモリモデル (WindowsおよびLinuxを含む)で使用されます。その場合は、funcの戻り値の型を_intptr_t_に変更する必要があります。 void *の代わりにintptr_tを使用する および なぜ/ Cで型キャストに「intptr_t」を使用するのか? を参照してください。

2番目の場合はそれほど問題ではありませんが、エンディアンの問題に対処するには、_intptr_t_:some_struct *ptr = (some_struct *)(intptr_t)func();以降のint value = (int)(intptr_t)ptr;を使用してキャストする必要があります。この問題の説明については、 GLib型変換マクロ を参照してください。

3
ecatmur