MAEC TOOL NEWS:
MAECT-M3T-CC32R-020716D
M32Rファミリ用クロスツールキットM3T-CC32Rの使用上の注意事項を連絡します。
- 除数が 0x80000000または -0x80000000※ である剰余演算子(%)または剰余代入演算子(%=)が記述されたプログラムに関する注意事項
※ C言語では、整定数 -0x80000000 は -0x7FFFFFFFF-1 と記述する必要がありますが、本資料では説明をわかりやすくするため、プログラム例を除いて-0x80000000 と表記します。
- 該当製品
M3T-CC32R V.1.00 Release 1 ~ V.3.20 Release 1
- 内容
除数が 0x80000000または -0x80000000※である剰余演算子(%)または剰余代入演算子(%=)が記述されたプログラムをコンパイルすると、以下の内部エラーが発生します。
error: code template illegal number '2147483648'
- 2.1 発生条件
- 以下3点をすべて満たす場合に発生します。
- (1) プログラム中に、剰余演算子(%)または剰余代入演算子(%=)がある。
- (2) (1)の被除数が、定数値ではない整数式 (変数等を含む整数式) である。
- (3) (1)の被除数と、(1)の除数の組み合わせが以下のいずれかである。
- (a) 被除数が符号無しで、除数が -0x80000000 である。
- (b) 被除数が符号無しで、除数が 0x80000000 である。
- (c) 被除数が符号つきで、除数が 0x80000000 である。
- 2.2 発生例
[sample1.c]
--------------------------------------------------------------------
unsigned long var1; /* (3)(a) */
void foo(void)
{
var1 %= (-0x7FFFFFFF-1); /* 発生条件(1),(2),(3)(a) */
}
--------------------------------------------------------------------
[sample2.c]
--------------------------------------------------------------------
long var1, var2; /* (3)(c) */
void foo(void)
{
var1 = (var2 - 1) % 0x80000000; /* 発生条件(1),(2),(3)(c) */
}
--------------------------------------------------------------------
[sample3.c]
--------------------------------------------------------------------
unsigned long var1;
short var2; /* (3)(c) */
void foo(void)
{
var1 = var2 % 0x80000000; /* 発生条件(1),(2),(3)(c) */
}
--------------------------------------------------------------------
[CC32Rのコマンド操作例(%はプロンプトを表します)]
--------------------------------------------------------------------
% cc32R -c sample1.c
% cc32R -c sample2.c
% cc32R -c sample3.c
--------------------------------------------------------------------
- 回避策
被除数が符号無しの場合は(1)、符号つきの場合は(2)の回避策をおこなってください。
- (1) 被除数が符号無しの場合
- 剰余演算子(%)は、「もとの除数の絶対値 - 1」をパラメータとするビットごとのAND演算子(&)に変更してください。
同様に、剰余代入演算子(%=)は、「もとの除数の絶対値 - 1」をパラメータとするビットごとのAND代入演算子(&=)に変更してください。
[sample1.c の変更例]
----------------------------------------------------------------
unsigned long var1;
void foo(void)
{
var1 &= 0x7FFFFFFF; /* |-0x7FFFFFFF-1| - 1 */
}
----------------------------------------------------------------
- (2) 被除数が符号つきの場合
- 発生条件(3)のとおり、除数が 0x80000000 である剰余演算のみ、問題が発生します。
この演算は、被除数が -0x80000000に等しい場合に 0 になり、それ以外は被除数の値になります。また、被除数がshort型やchar型の場合、演算は被除数の値になります。したがって、この剰余演算を以下のいずれかに変更してください。
- (a) 条件演算子(? :)を使って、被除数が -0x80000000 の場合は 0 を、それ以外では被除数の値になるような条件演算に変更してください。
- (b) 被除数がshort型やchar型の場合、剰余演算を省略してください。
[sample2.c の変更例]
--------------------------------------------------------------------
long var1, var2;
void foo(void)
{
long tmp;
var1 = ((tmp = (var2 - 1)) == (-0x7FFFFFFF-1) ? 0 : tmp);
}
--------------------------------------------------------------------
※ 上記では、変数tmpを使って var2の参照が1回で済むようにしています。
[sample3.c の変更例]
--------------------------------------------------------------------
unsigned long var1;
short var2; /* short型の被除数 */
void foo(void)
{
var1 = var2; /* 剰余演算を省略 */
}
--------------------------------------------------------------------
- 恒久対策
本内容は、次期バージョンアップの際に改修する予定です。