2017-02-13 29 views
2

質問はかなり簡単です。与えられたビットフィールドメンバのすべてのビットを1に設定する方法

警告なしで、バーのすべてのビットを1に設定するにはどうすればよいですか?

もちろん、私はauto v = Foo(); v.bar = ~0;を行うことができますが、GCCは私にこれを与える:

warning: large integer implicitly truncated to unsigned type [-Woverflow] 

私はいくつかの方法を試してみましたが、それは常に警告をレンダリング...

+1

なぜビットフィールドが必要ですか? (Btw、あなたの構造があまりにもboolとintを含むことになるという保証はありません)。 – StoryTeller

+0

M.b. memset()を使用できますか? – voltento

+0

'v.bar = UINT_MAX;'には何を得ますか? –

答えて

2

は(~0を使用しないでください右のサイズですので、のように組み合わせることができる、)常にフルintですが、~v.bar

v.bar |= ~v.bar; // or, 
v.bar ^= ~v.bar; 

を行う必要がありますそのトリックはどんなサイズでもあります。

ビットフィールドへの参照をバインドすることはできないので、残念ながら関数内ではうまくラップできません。あなたはそれをFoo&の関数にするか、マクロを使う必要があります。

PS。私はcoliruで投稿する前にこれをすばやく試して、ローカルでGCC(g ++)5.3.1と6.2.0を再確認しました。-Wallの診断は発行しません。

PPS。このテストコード付き

、GCCは符号なしのメンバーのための診断を生成します。

struct Foo { 
    int i : 2; 
    unsigned int u : 30; 
}; 

void bar() { 
    Foo f {0, 0}; 
    f.i ^= ~f.i; // OK 
    f.u |= ~f.u; /* warning: 
    large integer implicitly truncated to unsigned type [-Woverflow] 
    */ 
} 

、私はまた、通常ビットフィールドまたはビット単位の操作のための符号なし整数を好むだろうが、そうはG ++は、intと幸せと静かですここに。

+0

6.0.1以降の 'g ++'は、これらの構文について警告しています( 'gcc'はそうではありません)。 –

+0

'clang 3.8'は警告しません。 – olgierdh

+0

注:' Foo v; v.bar | =〜v.bar; 'は初期化されていない変数を使用するためUBになります。このコードはOPのコードのように、以前に初期化された 'v.bar'に依存しています。そして、ゼロで初期化されていることが分かっていれば、 'v.bar =〜v.bar 'で十分です。 –

1

これは私のために署名のないタイプのために働く。未定義の振る舞いでOKでない限り、すべてのビット操作は符号なしの型で行うべきであることに注意してください。

... 
    unsigned int bar : sizeof(int) * 8 - 2; 
... 

template <typename T, unsigned n> 
constexpr T onebits() 
{ 
    return 1 | (((1 << (n-2)) - 1) << 1); 
} 

v.bar = onebits<unsigned, sizeof(int) * 8 - 2>(); 
+0

それはまた非常にきちんとしています、あなたの貢献に感謝します! –

関連する問題