C言語の引数

RL78
CS+ 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から販売されてました。

  • ega258さん
    私の使用したのはCS+ですが
    まず
    インフォメーション・メッセージ出力を有効にするをはいにすると
    インフォメーション・メッセージ出力にConversion in argumentが出力されるようになり
    警告レベルの設定項目で
    インフォメーション・メッセージ出力を警告にするという項目があり
    それを有効にすると
    警告はしましたよ、ただそれをすると非常に多くの警告がでますので
    わずらわしいと思いますが。
  • 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となって不安ではありますが
    理解していれば特に危険ではないように思いますが

    この私の理解で正しかったですかね?

  • CC-RX では可能らしいので、実際のプログラム作成は CC-RL を使用して行い、チェックのみ CC-RX で行うという運用は可能だと思います。
    CC-RL に依存した記述をしている箇所は条件コンパイル等で避ければ問題ないでしょう。
    お勧めいたしません。
  • 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 にゼロ拡張されるだけなので値に変化は生じません。

    Wandboxで実行

    符号ありの値をよりサイズの大きな符号なしの型に変換した場合には仰られてるような符号拡張が行われるため注意が必要となります。

    Wandboxで実行

  • imudakさんfujita nozomuさん
    符号付きと符号なしを混同していたようですゼロ拡張でしたね
  • 結局のところ関数への引数をすべてポインタ渡しするのが最も現実的なのではないかなと思います。

    #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 でも同様です。

    Wandboxで実行

    無論、こういった書き方はお勧めいたしません。