1. ホーム
  2. c

[解決済み】「ポインタから異なるサイズの整数へのキャスト」エラーが発生するのはなぜですか?

2022-01-18 16:17:10

質問内容

次の行(pure c)は、次のようにきれいにコンパイルされます。 ウィンドウ (win7 64 bits + codeblocks 13 + mingw32) と デビアン (wheezy 32 bits + codeblocks 10 + gcc) で警告が表示されます。 カーリー (64 bits + codeblocks + gcc)です。何かコメントはありますか?つまり、同じ行がWindows & debianで何の警告もなくコンパイルされるのに、なぜこの警告が出るのでしょうか?

void* foo(void *dst, ...) {
    // some code
    unsigned int blkLen = sizeof(int); // this line ok.
    unsigned int offset = (unsigned int) dst % blkLen; // warning here!
    // some code cont...
}

codeblocksのメッセージは、「"」です。 のエラーが発生しました。 ポインタから異なるサイズの整数へのキャスト [-Werror=pointer-to-int-cast]"

注:私のコンパイラのオプションは -std=c99 -Werror -save-temps (3つのシステムで同じ)。

2を編集します。 以下のプリプロセッサの行を使って、なんとか警告を出さずにコンパイルできるようになりましたが。 Keith Thompson (下記参照) は、この問題に関して重要な指摘をしています。そこで、私の最後の決断は uintptr_t がベターな選択でしょう。

1を編集します。 皆さん返信ありがとうございました。すべての返信にあるように、この問題は32ビットと64ビットの問題です。私は以下のプリプロセッサの行を挿入しました。

#if __linux__   //  or #if __GNUC__
    #if __x86_64__ || __ppc64__
        #define ENVIRONMENT64
    #else
        #define ENVIRONMENT32
    #endif
#else
    #if _WIN32
        #define ENVIRONMENT32
    #else
        #define ENVIRONMENT64
    #endif
#endif // __linux__

#ifdef ENVIRONMENT64
    #define MAX_BLOCK_SIZE unsigned long long int
#else
    #define MAX_BLOCK_SIZE unsigned long int
#endif // ENVIRONMENT64

というように、問題の行を置き換えた。

unsigned int offset = (MAX_BLOCK_SIZE) dst % blkLen;

これで、すべてOKのようです。

どのように解決するのですか?

警告の理由は、コンパイラが、あなたが int を往復しています。これは64ビットマシンが登場する以前にはよく行われていたことで、安全でも合理的でもありません。もちろんここでは、コンパイラはあなたがこのようなことをしていないことを明確に知ることができますし、このような場合に警告が出ないようにするほど賢ければいいのですが、そうではありません。

警告や、変換後の値が負である場合の間違った結果という、より厄介な問題を回避する、クリーンな代替案は以下の通りです。

unsigned int offset = (uintptr_t) dst % blkLen;

をインクルードする必要があります。 stdint.h または inttypes.h を持つようにします。 uintptr_t を利用することができます。