4

MISRA C:2004 チェックをオンにして IAR Workbench コンパイラを使用しています。
フラグメントは次のとおりです。

#define UNS_32 unsigned int
UNS_32 arg = 3U;
UNS_32 converted_arg = (UNS_32) arg;
/* Error line --> */ UNS_32 irq_source = (UNS_32)(1U << converted_arg);

MISRA エラーは次のとおりです。 エラー [Pm136]: 基礎となる MISRA 型 "unsigned char" から "unsigned int" への不正な明示的変換 (MISRA C 2004 ルール 10.3)

unsigned char上記のコードには何も表示されません。

なぜミスラはここでエラーをスローしたのですか?での議論 左シフトとは異なる昇格規則を持つ可能性のある乗算について説明します。

私の理解では、コンパイラは式を小さいサイズに降格するのではなく、より大きなサイズのデータ​​型に昇格させる必要があります。

ここで実際に何が起こっているのですか?

コードを MISRA C:2004 に準拠させるにはどうすればよいですか?

編集1:

エラー行を次のように変更します。

UNS_32 irq_source = (UNS_32)((UNS_32) 1U << converted_arg);  

エラーが消えません。

4

3 に答える 3

4

最初の2番目の質問:

コードをMISRAC:2004に準拠させるにはどうすればよいですか?

これは、MISRA準拠の方法で次のように記述できます。

typedef unsigned int UNS_32;

UNS_32 test(void);
UNS_32 test(void)
{
  UNS_32 original_arg = 3U;
  UNS_32 irq_source = 1UL << original_arg;

  return irq_source;
}

最初の質問に戻る:

ここで実際に何が起こっているのですか?

最初のルール10.3は、複雑な整数式は、基になる型よりも広い型にキャストされてはならないことを示しています。

エラーメッセージを理解するための1つの鍵は、タイプの基礎となる概念です。これは、MISRA-C固有の概念です。要するに、定数の基礎となる型は、それが収まることができる最小の型です。この場合、言語タイプがあるにもかかわらず1U、基になるタイプがあります。unsigned charunsigned int

10.3ルールの背後にある理論的根拠は、操作の結果がパーツよりも大きいコンテキストで使用される場合を回避することです。この標準的な例は乗算です。ここで、alphaおよびbetaは16ビットタイプです。

uint32_t res = alpha * beta;

ここで、intが16ビットの場合、乗算は16ビットで実行され、結果は32ビットに変換されます。一方、intが32ビット以上の場合、乗算はより高い精度で実行されます。具体的には、これにより、たとえば0x4000と0x10を乗算した場合の結果が異なります。

MISRAルール10.3は、キャスト結果が一時的に配置され、後でより大きなタイプにキャストされるようにすることで、これを解決しました。そうすれば、あなたは何らかの方法でコードを書くことを余儀なくされます。

16ビット乗算を使用する場合:

uint16_t tmp = alpha * beta;
uint32_t res = tmp;

一方、意図が32ビット乗算である場合:

UNS_32 res = (UNS_32)alpha * (UNS_32)beta;

したがって、この場合、式1U << countが潜在的な問題になります。converted_argが16ビットより大きい場合、16ビットを使用するときに問題が発生する可能性がありますint。ただし、MISRAでは1UL << countまたはを書くことができます(UNS_32)((UNS_32)1U << original_arg)。後者の場合、MISRAチェッカーがエラーを発行したとおっしゃいましたが、私の場合はそうではないので、もう一度確認してください。

したがって、私の見方では、使用したMISRACチェッカーはルール10.3への違反を正しく識別しました。

于 2012-02-06T10:24:10.537 に答える
3

MISRA ルールで指定されている C89 では、末尾に a が付いた整数定数の型は、その値を表現できるUリスト「unsigned int、unsigned long int」の最初の型になります。これは、 の型が で1Uなければならないことを意味しますunsigned int

ビットごとのシフト演算子の定義は、各オペランドで整数昇格が実行され (これは を変更しませんunsigned int)、結果の型が昇格された左オペランドの型であることを指定します。この場合、 の結果の型(1U << converted_arg)は したがって ですunsigned int

ここでの唯一の明示的な変換は、このunsigned int値を にキャストすることですunsigned int。したがって、これはコンパイラが警告していることに違いありませんがunsigned char、目に見えるものはありませんが、これは、チェッカーにバグがあるように見えることを意味します。

ただし、技術的には、このキャスト from unsigned intto toは規則 10.3 に違反しているように見えます。規則 10.3 では、「複雑な式」の結果はより狭いunsigned intにのみキャストできるということです。また、同じ型へのキャストは明らかにより狭い型へのキャストではありません。

キャストは不要です。省略します。

于 2012-02-04T04:29:22.500 に答える