注意してくださいbitops.h
。明確に定義されたソースから未定義の動作を生成する可能性があります。
たとえば、C/C++ 言語 (セクション 5.8 を参照)の場合、シフトは負になることはできず、単語の長さと同じにすることも、単語の長さを超えることもできません。つまり、32 ビット値は [0,31] を含む範囲でのみシフトできます。
上記の例では、[0,31] 以外は「未定義」です。コンパイラは、問題のあるコードの削除、 の呼び出しabort()
、またはそれ自体全体のたわごとなど、未定義のコードに対して必要なことを自由に行うことができると思います。
多くのプログラムは、シフトと回転を悪用します。テスト/チェックする優れた方法は、John Regehr と Peng Li のInteger Overflow Checker (IOC)を使用することです。機能 ( ) を使用して Clang を簡単に構築-fcatch-undefined-ansic-behavior
できるため、これらのことを確認するためのツールを利用できます。
そうは言っても、以下は 3.8 カーネルのコードです<linux\bitops.h>
(2013 年 2 月 19 日ダウンロード)。プログラマーが0
(legal)のシフト サイズを送信すると、 (et al)<linux\bitops.h>
により不正なコードが作成されます。(word << (32 - shift))
カーネルのメーリング リストで指摘したところ、「カーネルは完全に標準に準拠しようとしていない」と言われました。カーネルの問題の一部は、Torvalds と彼の「GCC はくだらない」という態度にあるようです。彼は物事を正しく行うことも、静的解析などのツールを使用することもできません。また、彼の仲間の開発者の何人かは同じような傲慢さを持っています。
/**
* rol64 - rotate a 64-bit value left
* @word: value to rotate
* @shift: bits to roll
*/
static inline __u64 rol64(__u64 word, unsigned int shift)
{
return (word << shift) | (word >> (64 - shift));
}
/**
* ror64 - rotate a 64-bit value right
* @word: value to rotate
* @shift: bits to roll
*/
static inline __u64 ror64(__u64 word, unsigned int shift)
{
return (word >> shift) | (word << (64 - shift));
}
/**
* rol32 - rotate a 32-bit value left
* @word: value to rotate
* @shift: bits to roll
*/
static inline __u32 rol32(__u32 word, unsigned int shift)
{
return (word << shift) | (word >> (32 - shift));
}
/**
* ror32 - rotate a 32-bit value right
* @word: value to rotate
* @shift: bits to roll
*/
static inline __u32 ror32(__u32 word, unsigned int shift)
{
return (word >> shift) | (word << (32 - shift));
}
/**
* rol16 - rotate a 16-bit value left
* @word: value to rotate
* @shift: bits to roll
*/
static inline __u16 rol16(__u16 word, unsigned int shift)
{
return (word << shift) | (word >> (16 - shift));
}
/**
* ror16 - rotate a 16-bit value right
* @word: value to rotate
* @shift: bits to roll
*/
static inline __u16 ror16(__u16 word, unsigned int shift)
{
return (word >> shift) | (word << (16 - shift));
}
/**
* rol8 - rotate an 8-bit value left
* @word: value to rotate
* @shift: bits to roll
*/
static inline __u8 rol8(__u8 word, unsigned int shift)
{
return (word << shift) | (word >> (8 - shift));
}
/**
* ror8 - rotate an 8-bit value right
* @word: value to rotate
* @shift: bits to roll
*/
static inline __u8 ror8(__u8 word, unsigned int shift)
{
return (word >> shift) | (word << (8 - shift));
}