2010-05-26

「VC++10 のcstdintはバグっている」にたいするツッコミ

VC++10 の<stdint.h>, <cstdint>はバグっている (2) - 危ないRiSKのブログ

C99規格より、

INT_FASTN_MIN    −(2N−1 − 1)
INT_FASTN_MAX    2N−1 − 1

とすれば、INT_FAST16_MINは、int_fast16_tの実際のビット数にかかわらず、-(216-1 -1)に置き換わるべきであるし、INT_FAST16_MAXは、216-1 -1に置き換わるべきである。

int_fast16_tの具体的な型がなんであるかは、規定されていない。int_fast16_tがintのtypedefであったとしても、全く問題はない。現時点で、MSVC10の実装では、intになっている。

VC++10 の<stdint.h>, <cstdint>はバグっている (4) - 危ないRiSKのブログ

何も指定せず、普通に関数のオーバーロードをしているので、もちろんこれはC++のコードである。

ところで、先程も述べたのと同じ理由で、int_least8_tがintであったとしても、何の問題もない。重要なのは、intが8ビット以上あるかどうかだ。intが32bitの環境では、以下の実装は、well-formedである。

namespace std {
typedef int int_least8_t ;
typedef int int_least16_t ;
typedef int int_least32_t ;
}

つまり、std::is_same<int_least8_t, int_least16_t>::valueがfalseである保証はない。

以上の理由で、int_leastN_tで関数をオーバーロードするのは、規格上、おそらくは、undefined behaviorもしくは、unspecified behaviorになると思われる。上記のような実装の場合、オーバーロードすると、結局、どの型もintに過ぎないので、コンパイルエラーとなる。これは、規格が上記のような実装を認めている以上、コンパイラの責任ではない。

ただし、VCの実装では、int_least8_tはsigned charで、int_least32_tは、intなので、INTN_Cの挙動はおかしいと言える。しかし、そもそもcstdintで定義されているtypedefが、違う型である保証はない。とすれば、どうなったところで、文句はいえまい。

そもそもが鼻から悪魔を召喚するコードなのだから、どうなったところで、実装の責任ではないだろう。

なお、UINTN_Cが一部、signed型になるのは、これは仕方が無いのではあるまいか。もし、キャストすると、#ifで使えなくなる。そして、C99規格は、#ifで使えることを要求している。とすれば、何が出来るというのか。実装の問題ではなく、規格の問題である。

ちなみに、これは明らかに、規格の問題なのだが、どうせ劣ったC言語では、特に問題にならない。なぜなら、C99には、関数のオーバーロードはないし、autoもdecltypeもない。実際に違った型であったとして、Cからどうやって利用するというのか。Cの型システムはC++よりはるかに劣っているので、C++のような厳格な型システムを期待するのは無理である。

第一、プリプロセッサを用いている時点で、C規格が根本的に救いようのない劣った言語であることは間違いがない。C言語の規格がクソなのに、実装に文句を言っても仕方がない。

4 comments:

RiSK said...

Hatena の id:RiSK です。
エントリをあげてくださりありがとうございます。
(4) については間違っていることがすぐに分かったので,あのエントリを撤回しました。
ご指摘ありがとうございました。


で,(2) について。

> INT_FAST16_MINは、int_fast16_tの実際のビット数にかかわらず、-(216-1 -1)に置き換わるべきであるし、INT_FAST16_MAXは、216-1 -1に置き換わるべきである。

これは不正確だと思います。

7.18.2 幅を指定する整数型の限界値 に

> 7.18.2 の各箇条でのオブジェクト形式マクロ(217)は,
> で宣言されている型の最小値及び最大値を示す。
> (snip)
> この処理系定義の値は,値を厳密に規定する場合を除き,7.18.2 の各箇条で規定
>する値と同じ符号をもち,その値以上の大きさ(絶対値)をもたなければならない。

とあるからです。
1.型の最大値・最小値を表す
2.「厳密」指定がなければその値以上の大きさをもつ
この二点を満たさなければなりません。

hitoさんの指摘では 2 しか満たしていません。

私は 1 を満たすために int_fast8_t が int に適合している VC++10 は,
int 型の最大値・最小値と合致しているべきだと思います。
そして,これは 2 を自動的に満たします。

もっとも処理系定義の値なので MS がこれで正しいと主張するならば,
これが正しいことになるような気もしますが,
今の実装では INT_FAST8_MIN, INT_FAST8_MAX が使い物になりません。
MS 側のミスだと考えるのが自然だと思います。

RiSK said...

私のブログのコメント欄にも情報があります。
合わせてご覧ください。
こちら:
http://d.hatena.ne.jp/RiSK/20100524/1274668840#c

RiSK said...
This comment has been removed by the author.
RiSK said...

何度も訂正失礼…。
×int_fast8_t ○int_fast16_t
×INT_FAST8_MIN, INT_FAST8_MAX ○INT_FAST16_MIN, INT_FAST16_MAX
以上のように訂正します。