MSC TOOL NEWS: MSCT-CC16-970516D
M16ファミリ用クロスツールキットCC16のCコンパイラcc16(V.3.00 Release 1 以上) ご使用上の注意事項についてご連絡致します。
- ポインタを使用してデータを参照する場合の注意事項
- 1 問題内容
- 以下に示す問題発生条件(1)~(5)をすべて満たす場合、ポインタを使用してデータを参照する処理において、ポインタによるデータの読み出し命令が削除され、正しいコードが生成されない場合があります。
- [問題発生条件]
| (1) | コンパイル時に最適化レベル4を含むオプション(-O4, -O5, -O6, -O7, -O, -Otimeのみ, -Ospaceのみ)を指定している。 |
| (2) | ポインタを示す変数(ローカルまたはグローバル)にアドレスを代入している。 |
| (3) | 上記(2)のポインタに定数を代入している。 |
| (4) | ポインタを示す変数(ローカルまたはグローバル)にアドレスを代入している。 |
| (5) | ポインタを使用してデータを参照している。 |
- 2 記述例
--------------------------------------------------------------------
void foo(void)
{
unsigned short *a, *b, *c;
a = (unsigned short *)1000; /* 条件(2) */
*a = 2000; /* 条件(3) */
b = (unsigned short *)4000;
c = (unsigned short *)8000; /* 条件(4) */
*b = *c; /* 条件(5):*c の読み出し命令が
最適化により削除されてしまい、
*b には不正な値が代入されます。*/
}
--------------------------------------------------------------------
- 3 回避方法
- 以下に示す(1)~(3)の何れかの方法で回避してください。
| (1) | 最適化オプションとして、最適化レベル4を含まないオプション(-O0, -O1, -O2, -O3)を指定してコンパイルする。 |
| (2) | データを参照する処理に使用しているポインタ変数に volatile 宣言を行う。
--------------------------------------------------------------------
void foo(void)
{
unsigned short *a, *b;
volatile unsigned short *c; /* ポインタ変数に
volatile 宣言を行います。*/
a = (unsigned short *)1000;
*a = 2000;
b = (unsigned short *)4000;
c = (unsigned short *)8000;
*b = *c; /* *bには正しく*cが代入されます。*/
}
--------------------------------------------------------------------
|
| (3) | 上記問題発生条件に示す条件(2)または条件(4)のポインタ変数のどちらか一方をグローバル変数にし、アドレスを初期値として代入する。
--------------------------------------------------------------------
unsigned short *c=(unsigned short *)8000;void foo(void)
{
unsigned short *a, *b;
a = (unsigned short *)1000;
*a = 2000;
b = (unsigned short *)4000;
*b = *c; /* *bには正しく*cが代入されます。*/
}
-------------------------------------------------------------------- |
- 関数の引数のアドレスを使ってデータを参照する場合の注意事項
- 1 問題内容
- 以下に示す問題発生条件(1)~(4)をすべて満たす場合、関数の引数のアドレスを使ったデータの参照が、正しくできない場合があります。
- [問題発生条件]
| (1) | コンパイル時に-RBPPオプション(関数への引数渡しにレジスタを使用する)を指定している。 |
| (2) | 関数の引数の型が、char, short, unsigned char, unsigned short である。 |
| (3) | 上記(2)の引数を更新する前に、そのアドレスを参照している。 |
| (4) | 上記(3)のアドレスを使ってデータを参照している。 |
- 2 記述例
--------------------------------------------------------------------
#include "stdio.h" void test(short *d)
{
printf("%x", *d); /* 条件(4):正しく参照できません。 */
}
void foo(short data) /* 条件(2) */
{
test(&data); /* 条件(3) */
}
--------------------------------------------------------------------
- 3 回避方法
- 以下に示す(1)~(2)の何れかの方法で回避してください。
| (1) | -RBPP オプションを指定しない(関数への引数渡しにスタックを使用する)でコンパイルする。 |
| (2) | ローカルに変数を用意し、この変数のアドレスを使ってデータを参照する。 |
--------------------------------------------------------------------
#include "stdio.h" void test(short *d)
{
printf("%x", *d); /* 正しく参照できます。 */
}
void foo(short data)
{
short datax = data /* ローカルに変数を用意し、引数を代入します。*/
test(&datax); /* ローカルに用意した変数のアドレスを参照します。*/
}
--------------------------------------------------------------------