

MISRA 2020 Rule11.9では「マクロNULLは整数ヌルポインタ定数の形式のみ許されなければならない」とあります。

ポインタ変数をメンバにもつ集成体を初期化する際に、このルールを関連させた場合、0で初期化することは例外的にOKなのでしょうか。

マクロNULL「の方が良い」と思いますが、規格書等に明確な記載があれば展開して頂きたいです。

追記:適用される条件の一つに、「ポインタに代入される値として」とありますので以下記載方法にも関係があるかと思います。

例:

[code]

    struct S {
     int *p;
    }
    void func(void){
     struct S p = { 0 };
    }
    
[/code]


CC BY-SA 4.0
2021-02-03T09:10:11.150
73773
2021-02-04T01:47:18.090
2021-02-04T00:49:53.397
43811
43811
question
c
MISRA2020 Rule11.9 メンバにポインタ変数を持つ集成体の初期化について(マクロNULL or 0)


規格書に興味があるなら購入くださいお願いします。オイラは購入しています。引用はいいんようということなんですが、引用にとどまる範囲では全貌を知ることができない場合があります。

[c99](/questions/tagged/c99 "'c99' のタグが付いた質問を表示") JIS X 3010:2003 (ISO/IEC
9899:1999) 6.3.2.3 ポインタ  
値 `0` をもつ整数定数式又はその定数式を型 `void*` にキャストした式を、空ポインタ定数と呼ぶ。

この文言の意味は「整数リテラル `0` は、その必要があることが自明な時、任意に空ポインタ定数に変換される」です。つまり `char* p=0;`
は規格書上正当で `p` は空ポインタ (`nullptr`) となります。集成体の場合でも同様で提示例では `p.p` は空ポインタ定数で初期化されます。

必要が自明でない場合ってのは例えば `printf("%p\n", 0);` で、この場合 `0` を空ポインタ定数に変換しなければならないことは
**コンパイラにとっては非自明** です。ポインタ型の大きさと `int` の大きさが違う処理系ではこの `printf()`
は期待した動作をもたらさないでしょう。

あとはリンク先
[C言語のポインタ変数を含む構造体初期化について](https://ja.stackoverflow.com/questions/33824/)
で説明した通りです。

* * *

質問が編集された結果として内容が全く変わったので、変更分に関して追記（を更に変更）

MISRA は「たとえ言語規格書が認めていてもバグの元になりそうなものは禁じる」という代物です。ここはまさにそれで、コンパイル時に `int` の `0`
を導く定数式を `nullptr` に変換できるという仕様を

  * 言語規格書は認めている
  * MISRA は認めない (逸脱するなら文書を残せ）

ってだけのことです。なので [c99](/questions/tagged/c99 "'c99' のタグが付いた質問を表示")
的には完全に正当である提示ソースコードに対して MISRA は警告を発しているわけです。 MISRA に適合させるのが優先であるなら `={NULL}`
とすべきでしょうし、逸脱を選択して `={0}` とするのもありでしょう。その辺は政治的判断ってやつになります。

MISRA にせよ lint
にせよ他の静的解析ツールにせよ、ツールに人間が使われるのでは本末転倒です。ツールに使われた結果不要なソースコードの修正を行って逆に読みにくくなるとか管理しにくくなるとかあるくらいなら、適切に逸脱を選択しましょう。  
# と言っても上司とか依頼元とかが納得しない場合があって、だから政治的判断が必要


CC BY-SA 4.0
2021-02-03T21:54:15.267
73781
2021-02-04T01:47:18.090
2021-02-04T01:47:18.090
8589
8589
73773
answer