いくつかの理由から、あなたが読んだコードは非常に悪いものです。
まず第一に、ユーザーコードは決して定義すべきではありませんULONG_MAX。これは予約済みの識別子であり、コンパイラの実装によって提供される必要があります。
その定義は、プリプロセッサでの使用には適していません#if。そこでは、基本的な整数型の_MAXマクロを使用できる必要があります。
(unsigned long)0ただのがらくたです。その点で最近のすべての C 標準に準拠していないコンパイラがあることを知っ0ULていない限り、誰もが を使用する必要があります。(私は何も知りません。)
(理論的には) パディング ビットがある可能性がある~0ULため、その値にはEvenを使用しないでください。値のビット パターンを処理しないため、より適切です。符号なし整数型の保証された算術プロパティを使用します。は常に unsigned 型の最大値になります。そのため、パディング ビットがないことが絶対に確実なコンテキストでのみ使用できます。しかし、それをそのまま使用しても意味がありません。より良いサービスを提供します。unsigned long-1UL-1~unsigned long-1
あなたが観察したように、あることが知られている表現を「再キャスト」することunsigned longは、単に不必要です。それにバグがあるコンパイラは想像できません。
式の再キャストは、プリプロセッサで使用される場合は意味があるかもしれませんが、非常に制限された状況下でのみであり、そこでは異なる解釈がされます。
#if ((uintmax_t)-1UL) == SOMETHING
..
#endif
ここで、左側の値はUINTMAX_MAX、プリプロセッサおよび後のコンパイラ フェーズで評価されます。そう
#define UINTMAX_MAX ((uintmax_t)-1UL)
コンパイラの実装に適した定義です。
(uintmax_t)プリプロセッサの値を確認するには、内部にキャストではなく不明な識別子トークンが()あり、それが に評価されることを観察し0ます。マイナス記号はバイナリのマイナスとして解釈されるため、0-1ULどちらが符号なしであり、したがって型の最大値になります。ただし、そのトリックは、キャストに単一の識別子トークンが含まれている場合にのみ機能し、例のように3つ含まれている場合や、整数定数に-または+記号がある場合にのみ機能します。