RL78CS+ forCCでソフトを作っています。例えば、関数 void xxfunc(uint32_t, uint32_t) があったとします。メインで、 uint16_t aa; uint16_t bb; aa = 1000; bb = 6000; xxfunc(aa, bb);でコンパイルします。引数の型が合わないのでワーニングが出ると思いましたが出ませんでいた。暗黙の型変換だと思います。このような場合でもワーニングを出すことはできますか?
構造体に入れてしまえば引数型の違いは全てエラーにできますね。
#include <stdio.h> #include <stdint.h> #include <inttypes.h> typedef struct { uint16_t content; } uint16_s; typedef struct { int16_t content; } int16_s; typedef struct { uint32_t content; } uint32_s; typedef struct { int32_t content; } int32_s; uint32_s xxfunc(uint32_s x, uint32_s y) { uint32_s z = {x.content + y.content}; return z; } int main(void) { uint16_s aa = {1000}; int32_s bb = {6000}; uint32_s cc = xxfunc(aa, bb); printf("%"PRIu16 " + %"PRId32 " = %"PRIu32 "\n", aa.content, bb.content, cc.content); }
Wandboxで実行
勿論お勧めしません
本末転倒な感じがします。 ユルイのがCのメリットです。コンパイラーは適当に解釈してとにかく実行コードを作る、そして、それぞれのルールで人や静的解析ツールによりチェックする、が基本的な考えと思います。私のようなミニコンやマッキントッシュからスタートしたPASCALを好むプログラマはCユーザーから「ガチガチ」とバカにしたされたものです。 現状でPASCALは見ないですが、まだまだ、Adaなどは多く使用されているようです。Fujitaさんが示されてますが、マイコンの選択も含めて言語も再検討するのが良いように思えます。RXやRL78に関してはチェックしてませんがSHマイコン向けのAdaはGHSから販売されてました。
IKUZOさん、こんにちは。NoMaYです。その機能は、CC-RXにはありますが、CC-RL(とCC-RH)には無いのです。そして、CC-RXで検出されていても、今回は、RL78とCC-RLでのことなのです。この3種類のコンパイラは、必ずしも同一の仕様という訳ではなくて、C言語拡張仕様やコマンドラインオプションがそれなりにばらついています。そして、ワーニングレベルに関しては、CC-RXが最も高い設定が出来るような感じになってますね。
NoMaYさん CS+でもいろいろあってega258さんのはCC-RXでなくてCC-RLだったんですね 気が付くのが遅かったですね、なるほど思い込みで回答してたみたいです CC-RXのコンパイラーはCC-RLよりも親切というわけなんでしょうか コンセプトの違いなんでしょうか、uint16_tをuint32_tに変換する等とは0x7FFFをuint32_tでは変わらず0xFFFFであれば0xFFFFFFFFとなって不安ではありますが 理解していれば特に危険ではないように思いますが
この私の理解で正しかったですかね?
IKUZOさん
> 65534をuint32_tでは変わらず0xFFFFであれば0xFFFFFFFFとなって不安ではありますが
私が勘違いしているのでなければ勘違いされてるような気がします。
0xFFFFをuin32_tでキャストしても値は保持されるので、0xFFFFのままですね。
(-1)をuin32_tでキャストしたときは0xFFFFFFFFになるので、これと勘違いされてるのかと。
以下gccでの結果です。
$ cat test3.c #include <stdio.h>#include <stdint.h> int main(void) { uint16_t u16_m1 = (uint16_t)-1; uint32_t u32_cast = u16_m1; uint32_t u32_m1 = (uint32_t)-1; printf("0x%x: 0x%x: 0x%x\n", u16_m1, u32_cast, u32_m1); } $ gcc test3.c $ ./a.out 0xffff: 0xffff: 0xffffffff $
IKUZOさん、
> uint16_tをuint32_tに変換する等とは
> 0x7FFFをuint32_tでは変わらず0xFFFFであれば0xFFFFFFFFとなって不安ではありますが
uint16_t の値を uint32_t への変換では上位 16bit にゼロ拡張されるだけなので値に変化は生じません。
符号ありの値をよりサイズの大きな符号なしの型に変換した場合には仰られてるような符号拡張が行われるため注意が必要となります。
結局のところ関数への引数をすべてポインタ渡しするのが最も現実的なのではないかなと思います。
#include <stdio.h> #include <stdint.h> #include <inttypes.h> void xxfunc(uint32_t* z, const uint32_t* x, const uint32_t* y) { *z = *x + *y; } int main(void) { uint16_t aa = 1000; int32_t bb = 6000; uint32_t cc; xxfunc(&cc, &aa, &bb); }
CC-RL で警告が出ることを確認しました。
main.c(15):W0520167:"uint16_t __near *" 型の引数は型 "const uint32_t *__near" の引数と整合しません。 main.c(15):W0520167:"int32_t __near *" 型の引数は型 "const uint32_t *__near" の引数と整合しません。
gcc でも同様です。
無論、こういった書き方はお勧めいたしません。