JPCERT コーディネーションセンター

EXP14-C. char 型や short 型の値に対してビット単位の演算を行う際には整数拡張(integer promotion)が行われることに注意

このガイドラインは廃止され、以下のガイドラインに統合されました。

全ての char 型および short 型の値は、式中で使用される前に int 型もしくは unsigned int 型に整数拡張される。つまり、上位ビットが増えるということになる。これらの上位ビットは、unsigned char 型や unsigned short 型の場合はゼロ拡張され、signed char 型や signed short 型に対しては符号拡張される。それゆえ、int 型の値に対する算術演算は char 型や short 型に対する同様の演算と同じ結果の値をもたらすが、ビット単位の演算を行った場合にはびっくりするような影響を与える。

違反コード

以下のコード例では、int 型に整数拡張されたときの意外な結果を示している。

uint8_t port = 0x5aU;
uint8_t result_8 = ( ~port ) >> 4;

このコード例では、port の補数演算を行い、その結果を4ビット右シフトしている。これらの演算が8ビット整数に対して行われたとすると、result_80x0aU という値をとる。しかし、port は最初に32ビット整数に拡張されるため(signed になるか unsigned になるかは処理系に依存する)、以下のような結果になる。

port 0x0000005a
~port 0xffffffa5
~port >> 4 0x0ffffffa
result_8 0xfa
適合コード

以下の解決法では、補数演算の結果を8ビットに書き戻している。これにより、result_8 は期待通り 0x0aU になる。

uint8_t port = 0x5aU;
uint8_t result_8 = (static_cast<uint8_t> (~port)) >> 4;
リスク評価

ビット単位の演算を char 型や short 型のデータに対して行うと間違ったデータをもたらす恐れがある。

Recommendation Severity Likelihood Remediation Cost Priority Level
EXP14-C P9 L1
自動検出

Compass/ROSE はこのレコメンデーションへの違反を検出できる。

参考情報
翻訳元

これは以下のページを翻訳したものです。

EXP14-C. Beware of integer promotion when performing bitwise operations on chars or shorts

Top へ

Topへ
最新情報(RSSメーリングリストTwitter