2020/02/10(月) [n年前の日記]
#1 [prog] C言語にBooleanなんて型は無いことに今頃気づいた
Ubuntu Linux 18.04上で xpaint 2.9.1.4-3.2 を動かした際に、選択範囲をドラッグしただけで落ちる件。xpaint の PaintRegion.c 内で、Boolean を int として扱ってしまっている部分を修正すると落ちなくなるわけだけど。
考えてみたら、そもそもC言語にBooleanという型なんてあったっけ? と気になって。
ググってみたら…。うむ。無いよな。bool型はC99で用意されたらしいけど、それだって Boolean という型名ではない。
するとどこかで Boolean という型を定義しているはず…。探してみたら、Ubuntu の /usr/include/X11/Intrinsic.h の150行目あたりで以下の記述があった。
同じ操作をしても落ちない Debian 10.2 のほうはどうなっているだろう…。sudo apt install xpaint-dev で関連ヘッダファイル(*.h等)をインストールして確認してみた。しかしそちらも、Boolean には char が割り当てられていた。ココが int になってたら謎が解けたのだけどなあ…。
考えてみたら、そもそもC言語にBooleanという型なんてあったっけ? と気になって。
ググってみたら…。うむ。無いよな。bool型はC99で用意されたらしいけど、それだって Boolean という型名ではない。
するとどこかで Boolean という型を定義しているはず…。探してみたら、Ubuntu の /usr/include/X11/Intrinsic.h の150行目あたりで以下の記述があった。
typedef char Boolean;「char型を Boolean型として扱え」という定義なのかな。ソースの中に Boolean型が出てきたら、実はソイツは char型だぜ、みたいな。xpaint はコレを使いまくっているのではないか。たぶん。
同じ操作をしても落ちない Debian 10.2 のほうはどうなっているだろう…。sudo apt install xpaint-dev で関連ヘッダファイル(*.h等)をインストールして確認してみた。しかしそちらも、Boolean には char が割り当てられていた。ココが int になってたら謎が解けたのだけどなあ…。
◎ PaintRegion.cを眺めてみた。 :
xpaint の PaintRegion.c を眺めてみた。他の部分では ―― XtVaGetValues() や XtVaSetValues() を呼んでいるところでは、どういう型の変数を渡しているのかなと。
*1
件の関数に、(Widgetのポインタ、XtNtransparent、変数のアドレス、NULL) を渡す際には、変数は必ず int になってるなと…。例えば regionButtonRelease() 内では、変数 value が int で用意されてたりする。更に、どこを眺めても、その変数には数値が入ることを前提にして処理をしているように見える。
つまり、regionButtonPress() の中だけ、何故か Boolean (実は char) を用意して渡しているわけで、どう考えてもこれはバグだよなと。int を用意して渡すのが正しい。
しかし、Debian上では落ちない…。謎だ…。Ubuntu は何か特殊なことをしているのだろうか。もっともこの場合、Ubuntu の挙動が正しくて Debian の挙動がヤバイのだろうけど。
件の関数に、(Widgetのポインタ、XtNtransparent、変数のアドレス、NULL) を渡す際には、変数は必ず int になってるなと…。例えば regionButtonRelease() 内では、変数 value が int で用意されてたりする。更に、どこを眺めても、その変数には数値が入ることを前提にして処理をしているように見える。
つまり、regionButtonPress() の中だけ、何故か Boolean (実は char) を用意して渡しているわけで、どう考えてもこれはバグだよなと。int を用意して渡すのが正しい。
しかし、Debian上では落ちない…。謎だ…。Ubuntu は何か特殊なことをしているのだろうか。もっともこの場合、Ubuntu の挙動が正しくて Debian の挙動がヤバイのだろうけど。
◎ C言語って怖い。 :
それにしても、Boolean という型名からして true か false しか入らないのかなと予想したら、実は -128 〜 127 の数値を入れられますよ、てのは怖い。
*2
そして、そんな変数のポインタ(アドレス?)を関数に渡しても、これまた平気で処理するあたりがさらに怖い。わざわざ型を書いてる意味が無いのでは…。C言語は低級言語と揶揄されちゃうのもなんだかちょっと納得というか…。
*1: _Manpage of XtSetValues
や
_Ubuntu Manpage: XtVaSetValues, XtVaGetValues,
によると、XtVaGetValues() は X11 Widget が持ってる値を取得する関数で、XtVaSetValues() は値をセットする関数らしい。
*2: もっとも、C言語は、「0はfalse、0以外はtrue」という仕様なのでアレだけど。
*2: もっとも、C言語は、「0はfalse、0以外はtrue」という仕様なのでアレだけど。
[ ツッコむ ]
以上です。