2

同じリテラルを使用して、符号変換エラー (-Wsign-conversion) を発生させることなく、任意の幅の符号なし変数のすべてのビットを 1 に設定できますか?

-Wsign-conversion がなければ、次のことができます。

#define ALL_BITS_SET (-1)
uint32_t mask_32 = ALL_BITS_SET;
uint64_t mask_64 = ALL_BITS_SET;
uintptr_t mask_ptr = ALL_BITS_SET << 12; // here's the narrow problem!

しかし、 -Wsign-conversion では困惑しています。

error: negative integer implicitly converted to unsigned type [-Werror=sign-conversion]

(~0) と (~0U) を試しましたが、サイコロはありません。プリプロセッサは最初の変数を int に昇格させ、-Wsign-conversion をトリガーします。2 番目の変数は 32 ビットを超えて昇格せず、64 ビット変数の下位 32 ビットのみを設定します。

私は運が悪いのでしょうか?

編集: 明確にするために、プロジェクト全体の多くの場所で定義済みの ALL_BITS_SET を使用しているため、(~(uint32_t)0) や (~(uintptr_t)0) などをソースに散らかすことをためらっています。

4

3 に答える 3

0

試す

uint32_t  mask_32  = ~((uint32_t)0);
uint64_t  mask_64  = ~((uint64_t)0);
uintptr_t mask_ptr = ~((uintptr_t)0);

より明確な解決策が存在する可能性があります。これは少し衒学的ですが、ニーズを満たしていると確信しています。

于 2013-07-02T20:00:25.457 に答える
0

「暗黙的に符号なし型に変換された負の整数」という警告が表示される理由0は、リテラル整数値であるためです。リテラルの整数値として、intそれは符号付きの型である の型なので(~(0))、 は型の全ビット 1 の値としてint、 の値を持ちます(int)-1。もちろん、負の値を暗黙的に符号なしの値に変換する唯一の方法は、明示的に行うことですが、タイプに適したキャストを使用するという提案をすでに拒否しているようです。代替オプション:

明らかに、符号なしを否定することで符号なし型への暗黙的な変換を排除することもできます0...(~(0U))しかし、そうすると、unsigned int

わずかに異なるマクロを作成し、そのマクロを使用して変数を宣言します

`#define ALL_BITS_VAR(type,name) type name = ~(type)0`
`ALL_BITS_VAR(uint64_t,mask_32);`

しかし、それはまだ宣言に対してのみ機能します。

利用可能な最も広いタイプを使用して定義することを誰かが提案ALL_BITS_SETしましたが、開発環境がとてつもなく厳しいという理由で拒否されましたが、正直なところ、それはそれを行うための最良の方法です。開発環境が非常に厳格で、符号なしの値をより小さい型の符号なしの変数に代入することを禁止している場合 (その結果は非常に明確に定義され、完全に有効です)、もはや選択の余地はありません。タイプ固有のことをしなければなりません:

#define ALL_BITS_ONE(type) (~(type)0)
uint32_t mask_32 = ALL_BITS_SET(uint32_t);
uint64_t mask_64 = ALL_BITS_SET(uint64_t);
uintptr_t mask_ptr = ALL_BITS_SET(uintptr_t) << 12;

それで全部です。

(実際には、それだけではありません... GCCを使用していると言ったので、GCCのtypeof拡張機能でできることがいくつかありますが、渡す関数マクロなしで機能させる方法はまだわかりません変数に。)

于 2013-07-02T23:41:24.513 に答える