0とか1と書くよりも

マイコンのプログラムを静的解析にかけるといろいろ指摘が出てくる。

アライメントについての指摘は真面目に検討した記録を残さないとなとか、

符号あり/なしとかビット幅に関する指摘はほとんど空振りだなとか考えて見ていたが、

その中で気になったのがNULLポインタと_Bool型についての指摘である。


C言語でNULLポインタは 0 と書けばよいと理解していた。

(void*)0 をNULLと定義して使っている例も多いが、

本質的には 0 でNULLポインタの意味になるので問題ないと。

これは間違いではないのだが、単に0と書かれると数値なのかポインタなのか判然としない。

なので直接0と書かずに、定数NULLを使いなさいという指摘だった。


_Bool型、C99で導入された論理型である。

C言語に後から追加された型ということで、互換性の問題からアンダバーはじまりの型名になっている。

_Bool型も同じような話があり、真は1、偽は0で表すことができる。

ただ、これも一見するとただの数値型に見えるのでわかりにくい気がする。


例えばJavaとかだと null, true, false というのは予約語となっている。

しかし、Cにはこの手の予約語は存在していない。

なのでCでそれに相当するものは 0, 1 というただの数字だと考えていた。

でも、そんなコーディングしてると危険ですよと指摘されてしまったと。


調べたところ判明したのは所定のincludeを記載すれば、そのための定数が使えるということだった。

#include <stddef.h> とすると、NULLポインタを表す定数NULLが定義される。

#include <stdbool.h> とすると、定数true, falseが定義され、それぞれ_Bool型で真・偽を表す。

ついでに_Bool型のエイリアスとして bool型が使えるようになるらしい。

_Bool x,y = 0,     1;    //stdbool.hなし
bool x,y = false, true; //stdbool.hあり

stdbool.hなしだと上のような怪しげな表記になるが、stdbool.hだとわりと素直である。


そういえば uint32_t などの型名を使いたい場合も #include <stdint.h> と書かないといけないんだよね。

stdint.h はC99で追加された標準ライブラリで、ビット幅を使った型名が定義されている。

あまり使わないかも知れないけどポインタ型と同じ幅の整数型 uintptr_t なんてものも規定されている。


できるだけ新しい予約語を増やしたくないということで、

統一的な記号でも標準ライブラリのヘッダに組み込むようにして、

それが必要な場合はincludeするようにしているのだろう。

裏返せばincludeしなければ、これらの記号を別の使い方をしてもよい。

#define true 100
#define false -100

のようなstdbool.hとまるでちがう定義が過去になされていたとしても、

stdbool.hをincludeしなければ特に問題ないというわけである。


ちなみに2023年版のC言語である C23 が制定されたらしいのだが、

そこでは nullptr, bool, true, false が予約語になるらしい。

さらにNULLポインタを表す型として nullptr_t という型が規定されるらしい。

nullptr_t型はC++ではC++11で導入された概念らしく、これがCにも展開されたと。

さすがにC23にはコンパイラが対応していないわけだけど、

C23なら stdbool.h もなく true, falseが使えるし、

NULLポインタは nullptr と書くのが好ましい対応になる。

現時点で考えることではないでしょうけど。