

**聞きたいこと**  
掲題の警告を動作に支障なく解消したい

**問題のソースコード**

[code]

    unsigned char char_array1[8] = {0};
    unsigned char char_array2[8] = {0};
    unsigned long long_val;
    
    *(unsigned long*)char_array1 = long_val & *(unsigned long*)char_array2
    
[/code]

**説明**  
上記のソースはビルドは問題なく通っていますが、QACをかけたところ掲題の警告が出ました。  
（最後の1行のみ重要だと思うので宣言部に関しては割愛しております。）  
こちらを、修正前後で動作に支障なく警告を解消したいのですが良い方法はないでしょうか？  
ご教授のほどよろしくお願いいたします。


CC BY-SA 4.0
2020-07-02T09:00:09.927
68215
2020-07-03T00:45:38.830
2020-07-03T00:45:38.830
3060
40279
question
c
警告「異なるオブジェクトポインタ型へキャストしています。」を解消するには？


どういう目的でその処理が必要なのかちょっと場面の想像がつかないのですが、昔制御系のプログラムでフラグを扱ったりする際に、共用体を使っていたのを思い出しました。外していたらすみません。

共用体を使って書くと、

[code]

    typedef union {
        unsigned long long_val;
        unsigned char char_array[8];
    } MYDATA;
    :
    MYDATA data1 = { 0 };
    MYDATA data2 = { 0 };
    
    unsigned long long_val = 0;
    :
    (なんかの処理)
    :
    data1.long_val = long_val & data2.long_val;
    
[/code]

こんな感じです。QACかけるとどうなるかはちょっとわかりませんが、キャストがない分うまくいくのではないかと思います。


CC BY-SA 4.0
2020-07-02T11:27:56.793
68218
2020-07-02T11:27:56.793
9515
68215
answer


> 支障なく警告を解消したい

と言うよりも ソースコードの可読性を良くする方が先の気がします。

[code]

    *(unsigned long*)char_array1 = long_val & *(unsigned long*)char_array2
    
[/code]

の部分の処理は x86 系と 68000 系の CPU では実行結果が異なります。  
long を メモリーに 格納する順番が違うためです。

また、char の配列は 8文字 （8バイト) 確保しているのに  
`*(unsigned long*)` の コピーでは 領域の先頭の 4 バイトしか コピーしません。

char 型を 無理やり long にキャストする場合には 非常に危険で 注意が行為であることを  
教えてくれているので、そこを 設計として明確にしたうえで、誤りがあれば修正すればいいし  
問題なければ、警告を抑止する対策を行えばいいと思います。

ただ `QAC` という製品について詳しくないため、警告を抑止する方法はわかりません。

愚直に書き直すと

[code]

        unsigned long long_val2 = (char_array2[0] & 0xff) |
            ((char_array2[1] & 0xff) << 8) |
            ((char_array2[2] & 0xff) << 16) |
            ((char_array2[3] & 0xff) << 24);
    
        long_val2 = long_val & long_val2;
    
        char_array1[0] = (long_val2) & 0xff;
        char_array1[1] = (long_val2 >> 8) & 0xff;
        char_array1[2] = (long_val2 >> 16) & 0xff;
        char_array1[3] = (long_val2 >> 24) & 0xff;
    
[/code]

となります。(x86 系のCPUの場合)

まあ、こう書けば エラーは消えるし、CPU の違いによる動作の違いもありません。

これが意図している結果なのか仕様の確認が必要ですけどね・・。


CC BY-SA 4.0
2020-07-02T14:36:01.873
68221
2020-07-02T14:36:01.873
18851
68215
answer


オイラも共用体に１票を投じたいところですが既に良い回答がついているので別案

この件、そもそも `char char_array1[8];` が誤りな可能性が高くて

[code]

    unsigned long data1, data2;
    unsigned long long_val;
    data1 = long_val & data2;
    
[/code]

で十分なのではないかという疑惑がわきます。これだと `unsigned long`
の大きさが４バイトの処理系でも、８バイトの処理系でも無駄は発生しませんし、規格厳密一致です。 QAC も文句言わないでしょう。

提示コードは

  * `unsigned long` は（まあ普通） alignment 4 なのに対して
  * `unsigned char` は alignment 1 なので奇数アドレスに配置される可能性があり

よってオイラの同僚がこんなコードを書いていたらレビューで下記のような指摘をして要修正とします。

  * SH2 CPU などでは提示コードは動作保証がありません（バスエラー発生）
  * x86 でも境界整合違反で実行性能ペナルティが課せられる可能性がある

まあ具体的にどう直すとよいかは、そのコードの元々の目的次第なのでコード断片だけ見せられても判断できないです。通信電文のバイト列の一部ということならバリバリに
Endianess 依存しているなどの点で不合格ですし。


CC BY-SA 4.0
2020-07-03T00:40:02.457
68232
2020-07-03T00:40:02.457
8589
68215
answer