-1を使用してすべてのビットをtrueに設定しても安全ですか?


132

このパターンがCとC ++でよく使われるのを見てきました。

unsigned int flags = -1;  // all bits are true

これはこれを達成するための優れたポータブルな方法ですか?または使用している0xffffffffか、~0より良いですか?


1
わかりません。説明していただけますか?
corazza

8
コードの意味が明確かどうかが一番重要だと思います。-1常に機能しますが、コメントが必要であるという事実は、それが明確なコードではないことを示しています。変数がフラグのコレクションであることを意図しているのに、なぜ整数を割り当てるのですか?その型は整数でもかまいませんが、意味的には整数ではありません。あなたはそれをインクリメントしたり、乗算したりすることは決してないでしょう。したがって、私は0xffffffff移植性や正確さのためではなく、明確にするために使用します。
カムジャクソン

@CamJacksonコメントではなく、Cコードを書いている人なら誰でも値の表現方法に慣れているでしょう。
Miles Rout 2018

質問は元々CおよびC ++として適切にタグ付けされていました。C ++には2の補数を必要とする提案があるため、言語が異なる可能性があります。とはいえ-1、両方の言語で互換性のある下位互換性のあるソリューションであるという事実は変わりませんが、他の回答の推論の一部に影響を与える可能性があります。
エイドリアンマッカーシー、

回答:


154

これは最も簡単な方法であるため、表示されているとおりに実行することをお勧めします。-1whichを初期化すると、実際の符号の表現とは関係なく常に~動作しますが、正しいオペランドタイプを使用する必要があるため、意外な動作が発生する場合があります。そうして初めて、unsigned型の最も高い値が得られます。

考えられる驚きの例として、これを考えてみてください。

unsigned long a = ~0u;

必ずしもすべてのビット1からまでのパターンを格納するわけではありませんa。ただし、最初にすべてのビットが1のパターンを作成し、unsigned int次にそれをに割り当てaます。unsigned longより多くのビットがある場合に何が起こるかは、それらのすべてが1ではないということです。

そして、これを検討してください。これは2以外の補数表現では失敗します。

unsigned int a = ~0; // Should have done ~0u !

その理由は、~0すべてのビットを反転する必要があるためです。これを反転すると-1、2の補数のマシン(必要な値です!)で生成されますが、別の表現で生成さ-1ません。1の補数マシンでは、ゼロになります。したがって、1の補数マシンでは、上記はaゼロに初期化されます。

あなたが理解する必要があるのは、それはビットではなく値についてすべてであるということです。変数は値で初期化されます。初期化で初期化に使用される変数のビットを変更すると、値はそれらのビットに従って生成されます。a可能な最大値に初期化するために必要な値は、-1またはUINT_MAXです。第二は、の種類に依存しますa-あなたが使用する必要がありますULONG_MAXのためにunsigned long。ただし、1つ目はそのタイプに依存せず、最も高い値を取得するための優れた方法です。

私たちはされていないかどうかの話-1(それは常に持っていない)すべてのビット1を持っています。そして、私たちはすべてのビットが1であるかどうかについて話しているのではありません~0(もちろん、1が持っている)

しかし、私たちが話しているのは、初期化されたflags変数の結果が何であるかです。そのため、すべてのタイプとマシンでのみ-1機能します。


9
-1がすべて1に変換されることが保証されているのはなぜですか?それは規格によって保証されていますか?
2009

9
発生する変換は、ULONG_MAXの値が範囲内になるまで(C TC2ドラフトの6.3.1.3)、ULONG_MAXよりも1つずつ繰り返し追加されます。C ++でも同じですが、別の方法で正規化します(2 ^ nを法とする)。すべては数学的な関係に帰着します。
ヨハネスシャウブ-litb 2009

6
@litb:-1をキャストすることは確かに最大の符号なしの値を取得するための良い方法ですが、それは本当に説明的ではありません。これが_MAX定数が存在する理由です(C99でSIZE_MAXが追加されました)。確かに、C ++バージョンnumeric_limits<size_t>::max()は少し時間がかかりますが、キャストもそうです...
クリストフ

11
「-1にすべてのビットが1であるかどうかは関係ありません(常にそうであるとは限りません。そして、〜0にすべてのビットが1であるかどうかは関係ありません(もちろん、それはあります)。」-なに??? 全体のポイントすべてのビットを1に設定することだと私は思いました。これがフラグの機能です。あなたはビットを見てください。誰がその価値を気にしていますか?
mpen

14
@質問者が気にかけるマーク。「-1を使用してすべてのビットをtrueに設定しても安全ですか?」これは、どのビット-1がどのビットで表されているかを尋ねたり、どのビット~0が持っているかを尋ねたりしません。値は気にしなくてもかまいませんが、コンパイラは気にします。操作が値とともに、値によって機能するという事実を無視することはできません。のはで~0ない場合がありますが-1、これは必要な値です。私の回答と@Dingoの要約を参照してください。
Johannes Schaub-litb

49
  • unsigned int flags = -1; ポータブルです。
  • unsigned int flags = ~0; 2の補数表現に依存しているため、移植性はありません。
  • unsigned int flags = 0xffffffff; 32ビット整数を想定しているため、移植性はありません。

C標準で保証されている方法ですべてのビットを設定する場合は、最初のビットを使用します。


10
〜0(つまり、1の補数演算子)は2の補数表現にどのように依存していますか?
ドリューホール

11
これは逆です。2の補数表現に依存するフラグを-1に設定します。符号+マグニチュード表現では、マイナス1には2ビットのみが設定されています。符号ビットとマグニチュードの最下位ビットです。
Stephen C. Steel、

15
C標準では、ゼロのint値に符号ビットがあり、すべての値ビットがゼロであることを要求しています。1の補数の後、これらのビットはすべて1になります。すべてのビットが設定されたintの値は次のとおりです。符号と大きさ:INT_MIN 1の補数:-0 2の補数:-1したがって、「unsigned int flags =〜0;」というステートメントです。上記のいずれかの値がプラットフォームの整数表現と一致するように割り当てます。しかし、2の補数の「-1」は、すべてのフラグビットを1に設定する唯一のものです。
ディンゴ

9
@Stephen:表現については同意しました。しかし、int値がunsigned intに割り当てられると、unsignedはint値の内部表現を採用することでその値を取得しません(2の補数システムが一般的に機能する場合を除きます)。unsigned intに割り当てられるすべての値はモジュロ(UINT_MAX + 1)であるため、-1の割り当ては内部表現に関係なく機能します。
ディンゴ

20
@マーク:2つの操作を混乱させています。もちろん、すべてのビットが設定され~0int値を生成します。ただし、an intをanに割り当てても、必ずしも unsigned intが符号付きビットパターンと同じビットパターンを持つunsigned intわけではありません。これは常に2の補数表現でのみ当てはまります。1の補数または符号の大きさの表現では、負の値を結果に割り当てると、別のビットパターンになります。これは、C ++標準が符号付き->符号なし変換を、同じビットを持つ値ではなく、モジュロ等しい値であると定義しているためです。intunsigned int
スティーブジェソップ2010

25

率直に言って、すべてのfffの方が読みやすいと思います。それがアンチパターンであるというコメントに関して、すべてのビットが設定/クリアされていることを本当に気にかけているのであれば、おそらく変数のサイズを気にしている状況にあると私は主張します。 :: uint16_tなど


あなたがそれほど気にしない場合がいくつかありますが、それらはまれです。たとえば、Nビットのデータセットをそれぞれsizeof(unsigned)* CHAR_BITビットのチャンクに分割することによって機能するアルゴリズム。
MSalters 2009年

2
+1。データ型のサイズがFの数よりも大きい(つまり、すべてのビットをtrueに設定していない)場合でも、値を明示的に設定しているため、少なくともどのビットが「安全」であるかを知っています。使用する」..
mpen

17

上記の問題を回避する方法は、単に次のようにすることです。

unsigned int flags = 0;
flags = ~flags;

ポータブルで要領を得ています。


2
しかしその後、flagsとして宣言する能力を失いますconst
David Stone、

1
@DavidStoneunsigned int const flags = ~0u;

@Zoidberg '-2の補数以外のシステムでは機能しません。例えば、サインマグニチュードシステムで、~01に設定されたすべてのビットを有する整数であるが、あなたがそれを割り当てるときintunsigned変数flagsは、からの値変換を行う-2**31(32ビットを想定intする)(-2**31 % 2**32) == 2**31の整数であり、最初のビット以外のすべてのビットを1に設定
David Stone

それも、この答えが危険な理由です。@Zoidberg '-の答えは同じであるように見えますが、実際は同じではありません。ただし、コードを読む人として、なぜコードを初期化するために2つのステップを実行したのかを理解し、それを1つのステップに変更したくなるかもしれません。
David Stone

2
ええ、私はuあなたの答えのサフィックスに気づきませんでした。これはもちろん機能しますが、使用するデータ型をunsigned2回指定する(それ以上は指定しない)問題が依然としてあり、エラーが発生する可能性があります。ただし、割り当てと初期変数の宣言が離れている場合、エラーが発生する可能性が最も高くなります。
David Stone、

13

フラグにunsigned intを使用することは、C ++の最初の場所では良い考えではありません。ビットセットなどはどうですか?

std::numeric_limit<unsigned int>::max()0xffffffffunsigned intが32ビット整数であると想定しているため、より優れています。


私はこれが標準なので好きですが、言葉が多すぎてタイプを2回宣言することになります。0は任意の整数型にすることができるため、〜0を使用する方がおそらく安全です。(私はそれがあまりにもCのにおいがするのを知っていますが)
Macke

それが冗長であるという事実は利点として見ることができます。しかし、私も〜0が好きです。
エドゥアールA.

2
いずれにしても、unsigned int型をハードコーディングしているので、標準のUINT_MAXマクロを使用してワード数を軽減できます。

2
@Macke C ++ 11で型を指定することを避けることができautoます。auto const flags = std::numeric_limit<unsigned>::max()
David Stone、

11
unsigned int flags = -1;  // all bits are true

「これは、これを達成するための移植性の高い方法ですか?」

ポータブル? はい

良い? このスレッドに示されているすべての混乱から明らかなように、議論の余地があります。同僚のプログラマーが混乱なくコードを理解できるように十分に明確であることは、優れたコードを測定するための1つの側面です。

また、この方法ではコンパイラの警告が発生しやすくなります。コンパイラを損なうことなく警告を回避するには、明示的なキャストが必要です。例えば、

unsigned int flags = static_cast<unsigned int>(-1);

明示的なキャストでは、ターゲットタイプに注意を払う必要があります。ターゲットのタイプに注意を払っている場合は、他のアプローチの落とし穴を自然に回避できます。

私のアドバイスは、ターゲットのタイプに注意を払い、暗黙的な変換がないことを確認することです。例えば:

unsigned int flags1 = UINT_MAX;
unsigned int flags2 = ~static_cast<unsigned int>(0);
unsigned long flags3 = ULONG_MAX;
unsigned long flags4 = ~static_cast<unsigned long>(0);

これらはすべて正しく、他のプログラマーにとってより明白です。

C ++ 11の場合:を使用autoして、これらをさらに簡単にすることができます。

auto flags1 = UINT_MAX;
auto flags2 = ~static_cast<unsigned int>(0);
auto flags3 = ULONG_MAX;
auto flags4 = ~static_cast<unsigned long>(0);

私は、単に正しいよりも、明確で明白であると考える。


10

-1を符号なしの型に変換すると、すべて1になることが標準で保証されています。のようなものを明示的に記述しない限り~0U0は型unsigned intを持っているため、一般的には使用は好ましくなく、より大きな符号なし型のすべてのビットを埋めることはありません~0ULL。正気なシステムで~0は、と同じである必要があります-1が、標準では1の補数および符号/大きさの表現が許可されているため、厳密に言うと移植性はありません。

もちろん、0xffffffff正確に32ビットが必要だとわかっている場合は、いつでも書き込めますが、-1には、複数の型で機能するマクロなど、型のサイズがわからない場合でも、どのコンテキストでも機能するという利点があります、または型のサイズが実装によって異なる場合。あなたはタイプを知っている場合は、すべてのものを得るために別の安全な方法は制限マクロでUINT_MAXULONG_MAXULLONG_MAXなど、

個人的にはいつも-1を使います。それは常に機能し、あなたはそれについて考える必要はありません。


FWIW、私が使用する「すべて1ビット」を意味する場合は~(type)0(まあ、typeもちろん右側に記入してください)。ゼロをキャストしてもゼロになります。これは明らかであり、ターゲットタイプのすべてのビットを無効にすることはかなり明確に定義されています。しかし、実際にその操作が必要になるのはそれほど頻繁ではありません。YMMV。
ドナルフェロー2010

6
@ドナル:あなたは単に間違っています。Cは、符号なしの型に適合しない値を変換するとき、値が2 ^ nを法として縮小されることを指定します。ここで、nは宛先の型のビット数です。これは、符号付きの値とより大きな符号なしの型の両方に適用されます。2の補数とは関係ありません。
R .. GitHub ICE HELPING ICEの停止

2
彼らそれを同じように実装しますが、それは簡単です。符号付きのものや命令の代わりに、符号なしの減算オペコードを使用するだけですneg。偽の符号付き算術動作をするマシンは、別々の符号付き/符号なし算術演算コードを持っています。もちろん、本当に優れたコンパイラーは、符号付きの値であっても、常に符号付きのオペコードを無視するため、2の補数を無料で取得できます。
R .. GitHub ICE HELPING ICEの停止

1
@R .: は、よりも狭い符号なしの型であるvar = ~(0*var)ためvar、失敗しintます。たぶんvar = ~(0U*var)?(個人的には-1、私はまだ好みます)。
ca

1
この答えはヨハネスシャウブの答えよりもはるかに明確です。ただし、キャストなしで負のリテラル整数を符号なしの型に割り当てると、通常、コンパイラの警告が表示されます。警告を抑制するにはキャストが必要です。これはとにかくターゲットタイプに注意を払わなければならないことを意味します。そのため、UINT_MAXまたはULONG_MAXを使用して、標準の細部に頼るのではなく明確にすることで、多くの仲間のプログラマーを明確に混乱させることができます。 。
エイドリアンマッカーシー

5

#include <limits.h>あなたがインクルードの1つを持っている限り、あなたはただ使うべきです

unsigned int flags = UINT_MAX;

longに相当するビットが必要な場合は、

unsigned long flags = ULONG_MAX;

これらの値は、符号付き整数の実装方法に関係なく、結果のすべての値ビットが1に設定されることが保証されています。


1
あなたが提案した定数は実際にはlimits.hで定義されています-stdint.hには追加の整数型の制限が含まれています(固定サイズの整数、intptr_tなど)
Christoph

5

はい。他の回答で述べたように、-1は最も移植性があります。ただし、これはあまり意味がなく、コンパイラの警告をトリガーします。

これらの問題を解決するには、次のシンプルなヘルパーを試してください:

static const struct All1s
{
    template<typename UnsignedType>
    inline operator UnsignedType(void) const
    {
        static_assert(std::is_unsigned<UnsignedType>::value, "This is designed only for unsigned types");
        return static_cast<UnsignedType>(-1);
    }
} ALL_BITS_TRUE;

使用法:

unsigned a = ALL_BITS_TRUE;
uint8_t  b = ALL_BITS_TRUE;
uint16_t c = ALL_BITS_TRUE;
uint32_t d = ALL_BITS_TRUE;
uint64_t e = ALL_BITS_TRUE;

3
Cプログラマーとして、このようなコードは夜に私に悪い夢を与えます。
jforberg 2015

そして、符号付き整数ALL_BITS_TRUE ^ aがどこにaあるようなコンテキストでこれを使用するとどうなりますか?タイプは符号付き整数のままで、ビットパターン(オブジェクト表現)はターゲットが2の補数かどうかに依存します。
Peter Cordes

いいえ、あいまいであるALL_BITS_TRUE ^ aため、コンパイルエラーが発生しますALL_BITS_TRUEuint32_t(ALL_BITS_TRUE) ^ aただし、のように使用できます。あなたは上でそれを自分で試すことができますcpp.sh :)今日では、私は追加したいstatic_assert(std::is_unsigned<UnsignedType>::value, "This is designed only for unsigned types");operator、ユーザーが使用しようとしていないことを確認しますint(ALL_BITS_TRUE)。答えを更新します。
ダイヤモンドパイソン

3

-1のことはしません。(少なくとも私にとっては)直感的ではありません。符号付きデータを符号なし変数に割り当てると、本来の順序に違反するように見えます。

あなたの状況では、私は常にを使用します0xFFFF。(もちろん、可変サイズには適切な数のFを使用してください。)

[ところで、実際のコードで-1のトリックが行われることはほとんどありません。]

あなたが本当にvairable内の個々のビットを心配している場合また、固定幅の使用を開始することをお勧めだろうuint8_tuint16_tuint32_t種類。


2

IntelのIA-32プロセッサでは、0xFFFFFFFFを64ビットレジスタに書き込んで、期待どおりの結果を得ることができます。これは、IA32e(IA32の64ビット拡張)が32ビットのイミディエイトのみをサポートするためです。64ビット命令では、32ビットの即値が64 ビットに符号拡張されます。

以下は違法です:

mov rax, 0ffffffffffffffffh

以下はRAXに64 1を置きます:

mov rax, 0ffffffffh

完全を期すために、以下ではRAX(別名EAX)の下部に32 1を配置しています。

mov eax, 0ffffffffh

実際、64ビット変数に0xffffffffを書きたいときにプログラムが失敗し、代わりに0xffffffffffffffffを取得しました。Cでは、これは次のようになります。

uint64_t x;
x = UINT64_C(0xffffffff)
printf("x is %"PRIx64"\n", x);

結果は次のとおりです。

x is 0xffffffffffffffff

私はこれを0xFFFFFFFFが32ビットを想定していると答えたすべての回答へのコメントとして投稿することを考えましたが、多くの人が答えたので、別の回答として追加すると思いました。


1
おめでとうございます。コンパイラのバグを見つけました!
tc。

これはバグとして文書化されていますか?
Nathan Fellman

1
がのUINT64_C(0xffffffff)ようなものに拡張すると仮定すると0xffffffffuLL、それは間違いなくコンパイラのバグです。C規格では主にについて説明しており、で表される値0xffffffffは4294967295(36893488147419103231ではない)であり、符号付き整数型への変換はありません。
tc。

2

問題の非常に明確な説明については、litbの回答を参照してください。

私の意見の相違は、厳密に言えば、どちらの場合も保証がないということです。すべてのビットが設定されているため、「ビット数の2の1乗」の符号なしの値を表さないアーキテクチャは知らないが、ここに標準が実際に言う(3.9.1 / 7 plus注44):

整数型の表現は、純粋な2進記数法を使用して値を定義します。[注記44:] 2進数の0と1を使用する整数の位置表現。連続するビットで表される値は加算的であり、1で始まり、2の連続する整数の累乗が乗算されます。最高位。

そのため、ビットの1つがまったく何でもない可能性があります。


一般的に、パディングビットの値はわかりません。そして、必要に応じて、それらのトラップ表現を生成できるため(そしてシグナルを発生させる可能性があるため)、危険にさらされる可能性があります。ただし、stdにはパディングビットがないunsigned charが必要であり、c ++標準の4.7 / 2では、整数を符号なしの型に変換すると、結果の符号なし変数の値は、ソース整数値と一致する最小値になります。 (2 ^ nを法とするn ==符号なし型のビット数)。次に(-1)==((2 ^ n)-1)(mod 2 ^ n)です。2 ^ n-1は、すべてのビットが純粋な2進数で設定されています。
ヨハネスシャウブ-litb 2009年

私たちがした場合、実際に符号なしの型のオブジェクト表現のすべてのビット1を持つようにしたい、私たちはmemsetのが必要になります。しかし、それによってトラップ表現を生成することができます:(とにかく、実装にはおそらく符号なし整数を少し捨てる理由がないので、値を格納するためにそれを使用します。いくつかのばかげた無意味なビットを持っていることからの解釈だと思います(char / signed char / unsigned charの一部であり、これらを含むことはできません)+1もちろん:)
Johannes Schaub-litb

結局のところ、標準は4.7 / 2でどの表現を参照するかがより明確になると思います。それがオブジェクト表現を参照している場合、ビットをパディングする場所はもうありません(私は何も問題がないように議論している人を見てきました)。値ビットに来年5月の巣をして、ビットをパディング-しかし、私は、4.7 / 2で、すべてがとにかく値についてですので、それは値表現(の話だと思う。
ヨハネス・シャウブ- litb

1
規格はかなり明確に「2の補数、1の補数、および符号付きの大きさ」の表現を念頭に置いているようですが、何も除外したくありません。表現のトラッピングについても興味深い点があります。私の知る限り、引用したビットは、標準に関する限り、「純粋なバイナリ列挙システム」の定義です-末尾の「例外」ビットは、-1のキャストが保証されているかどうかについての私の唯一の疑問です作業。
Jamesホプキン、

2

0xFFFF(あるいは0xFFFFFFFF、など)読みやすくすることができ、それ以外のポータブルだろうコードで移植性を破ることができます。たとえば、データ構造内の特定のビットが設定されている項目の数をカウントするライブラリルーチンを検討してください(正確なビットは呼び出し側によって指定されます)。ルーチンは、ビットが何を表しているかに関して完全に不可知かもしれませんが、それでも「すべてのビットが設定されている」定数を持つ必要があります。このような場合、どのビットサイズでも機能するため、-1は16進定数よりもはるかに優れています。

typedefビットマスクに値が使用されている場合のもう1つの可能性は、〜(bitMaskType)0を使用することです。ビットマスクは唯一の16ビット型であることを起こる場合、その式は(「intは」そうでない場合は32ビットになる場合も含む)の16ビットが設定されていますが、16ビットが必要とされるすべてのだろうから、物事はうまくする必要があります提供する 1つをタイプキャストでは適切なタイプを実際に使用します。

ちなみに、longvar &= ~[hex_constant]16進定数が大きすぎてに収まらない場合、フォームの式は厄介ですintが、には収まりunsigned intます。intが16ビットの場合、longvar &= ~0x4000;またはlongvar &= ~0x10000; は1ビットをクリアしますがlongvarlongvar &= ~0x8000;ビット15およびそれより上のビットはすべてクリアします。適合する値はint、型intに適用される補数演算子を持ちますが、結果はに拡張されlong、上位ビットを設定します。値が大きすぎるunsigned intと、補完演算子がtypeに適用されlongます。ただし、これらのサイズの間にある値は、補完演算子をtypeに適用し、unsigned intその後、long符号拡張なしでtypeに変換されます。


1

実用的に:はい

理論的には:いいえ。

-1 = 0xFFFFFFFF(または、プラットフォーム上のintのサイズ)は、2の補数演算でのみ真になります。実際には機能しますが、2の補数表現ではなく実際の符号ビットを取得できるレガシーマシン(IBMメインフレームなど)が世の中にあります。提案する〜0ソリューションはどこでも機能するはずです。


6
私もそう言った。しかし、その後、私は間違っていることに気付きました。値の表現に関係なく、-1が常に変換ルールの下で符号なしのmax_valueに変換されるためです。少なくとも、C ++にはありますが、渡すC標準がありません。
スティーブジェソップ

6
あいまいさがあります。-1は0xFFFFFFFFではありません。ただし、符号なし整数(32ビット)に変換すると、-1は0xFFFFFFFFになります。それが、この議論を難しくしている理由だと思います。それらのビット文字列について話すとき、多くの人は非常に異なることを心に留めています。
Johannes Schaub-litb 2009

1

他の人が述べたように、-1は、すべてのビットが1に設定された符号なし型に変換される整数を作成する正しい方法です。ただし、C ++で最も重要なことは、正しい型を使用することです。したがって、あなたの問題に対する正しい答え(あなたが尋ねた質問への答えを含む)はこれです:

std::bitset<32> const flags(-1);

これには常に、必要なビットの正確な量が含まれます。std::bitset他の回答で述べたのと同じ理由で、すべてのビットが1に設定されたa を作成します。


0

-1では常にすべての使用可能なビットが設定されるため、これは確かに安全ですが、私は〜0の方が好きです。-1はunsigned int。にはあまり意味がありません。0xFF型の幅にもよりますので・・・良くありません。


4
「0xFF ...はタイプの幅に依存するので良くない」これが唯一の正しい方法だと思います。プログラムでは、各フラグ/ビットの意味を明確に定義する必要があります。あなたはフラグを格納するために、最低32ビットを使用していることを定義するのであれば、あなたはint型の実際のサイズは32または64であるかどうか、これらの32ビットを使用するために自分自身を制限する必要があります
ファンパブロCalifano

0

私は言う:

int x;
memset(&x, 0xFF, sizeof(int));

これにより、常に望ましい結果が得られます。


4
9ビット文字のシステムにはありません!
tc。

0

符号なし型のすべてのビットを1に割り当てるという事実を活用することは、指定された型の可能な最大値を取得することと同等
であり、質問のスコープをすべての符号なし整数型に拡張します。

CとC ++の両方で、符号なし整数型(unsigned int、uint8_t、uint16_tなど)に-1を割り当てると機能します。

別の方法として、C ++の場合、次のいずれかを行うことができます。

  1. 含め<limits>て使用するstd::numeric_limits< your_type >::max()
  2. 書くカスタムテンプレート機能を(先の型が実際にunsigned型である場合、これはまた、いくつかの健全性チェック、すなわちを可能にします)

割り当てに-1は常に説明用のコメントが必要になるため、目的を明確にすることができます。


0

タイプを繰り返さないようにしながら、意味を少し明確にする方法:

const auto flags = static_cast<unsigned int>(-1);

-6

はい、表示されている表現は非常に正確です。逆の方法でuを実行すると、すべてのビットを反転する演算子が必要になりますが、この場合、マシンの整数のサイズを考慮すると、ロジックは非常に簡単です。

たとえば、ほとんどのマシンでは、整数は2バイト=保持できる最大値は16ビットです2 ^ 16-1 = 65535 2 ^ 16 = 65536

0%65536 = 0 -1%65536 = 65535 1111 ............. 1に対応し、すべてのビットが1に設定されます(剰余クラスmod 65536を考慮する場合)。まっすぐ進む。

私は推測する

いいえ、もしあなたがこの概念を考えるなら、それは完全にunsigned intのための食事であり、それは実際にうまくいきます

次のプログラムの断片を確認してください

int main(){

unsigned int a=2;

cout<<(unsigned int)pow(double(a),double(sizeof(a)*8));

unsigned int b=-1;

cout<<"\n"<<b;

getchar();

return 0;

}

bの回答= 4294967295 whcihは4バイト整数で-1%2 ^ 32です

したがって、符号なし整数に対しては完全に有効です

不一致がある場合は、plzzレポート


9
2つのコメント:最初に、「ほとんどの」マシンの整数のサイズについて、あなたはまったく間違っています。2番目に、ur txt izは非常にハード2です。わかりやすい英語をご利用ください。
Konrad Rudolph
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.