C言語の整数型が可変長なのは設計ミスではない

C's Flexible Integer Sizes Were Not a Design Mistake

C言語の整数型が可変長なのは設計ミスではない

C言語のintやlongが固定サイズでないのは、よく設計ミスと批判される。しかし1970年代、コンピュータのワード長は12ビットから60ビットまでバラバラで、文字コードも6ビット、7ビット、9ビットと統一されていなかった。Cはそうした多様なマシンで効率的に動く移植性を実現するため、整数型をマシンの自然なサイズに委ねた。intが32ビットを意味するようになったのは、ずっと後のことだ。

「プレーンなintオブジェクトは、実行環境のアーキテクチャが示唆する自然なサイズを持つ。」
  1. adrian_b

    Cの柔軟な整数サイズが、作成当時まだ必要だったことには同意する。当時は、いくつかの重要なコンピュータが2の累乗ではないワードサイズを持っていたからだ。

    とはいえ、私がプログラミングにCを使い始めたのは1990年、Microsoft CとBorland Turbo Cのコンパイラにアクセスできるようになった時だった。

    その時点で、36年前には、Cの柔軟な整数サイズはすでに時代遅れだった。

    それ以来今日まで、サーバーやワークステーションから最小のマイクロコントローラまで、実にさまざまなコンピュータでCを使ってきたが、柔軟な整数サイズの存在が生み出す移植性の問題を山ほど見てきた。

    移植性の問題がなかったプログラムは、柔軟な整数サイズを一切使わず、8ビット、16ビット、32ビット、64ビットといった明確なサイズの整数だけを使っていたものだけだった。

    sizeofはメモリ割り当てやコピーの問題を解決するが、予期しない整数オーバーフローの防止には役立たない。なぜなら「char」のサイズすら不明な場合があり、たとえ「char」のサイズがわかっても、異なる整数サイズごとにオーバーフローをチェックまたは防止する複数のパスを持つコードを書くのは非常に面倒だからだ。

    柔軟な整数サイズがうまく機能するのは、古いコンピュータのように整数オーバーフローがハードウェア例外を発生させる場合だけであり、その場合オーバーフローハンドラをインストールすれば、ネイティブ整数のサイズに関係なくCコードが正しく動作するようになる。

  2. layer8

    > char、int、short、long といった言語の型は、メモリ上で何バイトを占めるかの保証がない。

    Charは実際にはCによってメモリ上で正確に1バイトを占めることが保証されている。ただ、Cではバイトが8ビットより大きいことがあるだけだ。「バイト」は単にポインタでアドレス指定できる最小のメモリ単位である。

    記事のさらに下の方で、「Cはcharが少なくとも8ビット(CHAR_BIT >= 8)であることを要求し、正確に8ビットではない」と認めており、9ビット(および36ビットのint)を持つC実装の例としてHoneywell 6000に言及している。

    コンピューティングの歴史において、バイトのサイズはハードウェア依存であり標準化されていなかった。Wikipediaの「byte」の記事は、Knuthの1968年のTAOCPを引用しており、そこではバイトは「不特定量の情報を含み、少なくとも64の異なる値を保持でき、最大100の異なる値を保持できる単位」を指す。したがって、バイナリコンピュータではバイトは6ビットで構成されなければならない。

  3. InvisibleUp

    柔軟な整数サイズが最も問題になるのはABIを扱うときだ。ABIは動的リンクが存在する前はあまり関心事ではなかったが、今日では非常に大きな関心事である。また、なぜかライブラリABIを定義する標準的な方法はCヘッダで行うと決めてしまった。そのため、誰もが整数サイズを正確に定義すること、およびsize_tやintmax_tのようなより難解な型についても気を配らなければならない。これに関する優れた記事はこちら: https://thephd.dev/to-save-c-we-must-save-abi-fixing-c-funct...

  4. nayuki

    記事の中のいくつかのコード片は怪しく見える:

    #define LUAI_IS32INT ((UINT_MAX >> 30) >= 3)

    もしunsigned intがたった16ビット幅なら、`65535 >> 30`は型の幅よりも多い位置をシフトすることになり、未定義動作になるはずでは?

    #define NB CHAR_BIT

    #define MC ((1 << NB) - 1)

    もし(記事で言及されているような)CHAR_BITが16でintが16ビットのDSPマシンなら、`1 << NB`は`1 << 16`となり、型の幅と同じだけシフトすることになり、これも未定義動作だと私は思う。

    Cの柔軟な整数サイズが良いか悪いか、またそれが言語の普及に役立ったかどうかに関わらず、マシン間で移植可能なコードを書きたいなら、固定サイズ整数を持つ言語に比べてより多くの努力を払わなければならないことは否定できない。これが重要かどうかは状況と意見の問題だ。

    それ以外に、各整数型のビット幅を設定でき、`x operation y`がどの出力整数型に昇格されるかを示すシミュレータを作った。https://www.nayuki.io/page/summary-of-c-cpp-integer-rules の「Conversion rules simulator」セクションを参照。

  5. codedokode

    うまくいかなかったと思う。なぜなら「int」のサイズが異なるとプログラミングが難しくなるからだ。例えば、システムが最大10万件のレコードを管理しなければならないとする。レコード番号にintを使えるだろうか?もし16ビットだったら?マシン間でデータを送る必要がある場合、サイズが異なりうる「int」をどう使えばいいのか?

    おそらく誰かが不便に気づき、64ビットマシンでもintは依然として32ビットで64ビットではない。

    16ビットintや9ビットバイトのコンピュータはずっと昔に消えたが、言語は依然としてその遺産を背負わなければならない。

  6. habitue

    意図的だったのは確かだ。特定の種類の問題を解決しようとする試みだった。

    しかし後から振り返ると、それは間違いだった。

    証拠:世界が64ビットに移行したとき、amd64でintを単に8バイトにするのではなく、そうしなかった。これは、よりよく理解した後で設計が正しくなかったことを明確に認めたものだ。

  7. stkdump

    問題は、伝統的な型と(u)intN_tを混ぜ始めたときに始まる。後者は単に内部型の別名であり、オーバーロード解決を乱すからだ。関連するすべてのプラットフォームは、char、short (int)、int、long long (int)のサイズについてほぼ合意している。long (int)については意見が異なるため、int64_tはlong (int)またはlong long (int)のいずれかを使うかもしれない。

    したがって、今日における最善の解決策は、char、short、int、long longだけを使い(これらがそれぞれ正確に8、16、32、64ビット幅であると強く仮定して)、longやlong doubleは決して使わず、(u)intNN_tも決して使わないことだ。そうすれば問題ない。

    過去のこれらの注意点(しかしintは16ビットか36ビットかもしれない)は、まさにそれだ。過去の産物。歴史的な好奇心。今日や未来には関係ない。いや、将来のプラットフォームがサイズを変えるなどとは一瞬たりとも信じない。

    プラットフォームはcharの符号についても依然として意見が分かれているので、8ビットの数値型(ASCII文字型とは対照的に)が必要な場合は、常にsigned charまたはunsigned charを明示的に指定すべきである。どちらもcharとは別の型だ。

    さらに注目すべき点:プラットフォームはリトルエンディアン(いわゆる「ネットワークバイトオーダー」は死んでおり、新しいプロトコルで決して使うべきではない。全員に変換を強いるからだ)やfloatとdoubleのIEEEメモリ表現についても合意している。一般通念に反して、主要な浮動小数点演算(+,-,*,/,==,<,>,<=,>=)も正確に定義されており、[…]

  8. quelsolaar

    良い記事だ。

    Cはこの柔軟性がなければおそらく生き残らなかっただろう。

    しかしそれは単に歴史的なことではない。今日でも、DSPのように32ビットサイズのcharを持つ現代のプラットフォームがある。それはアドレス指定可能な最小の型だからだ。これらのプラットフォームはツールチェーンをCに依存しており、たとえほとんどの「移植可能な」Cがそれらで正しく動作しなくてもそうだ。そのようなハードウェアを構築でき、それらをプログラムするために新しい言語や方言を発明する必要がないという事実は、世界にとって大きな勝利だ。

    <編集> 最初に読んだときDSPに関する脚注を見落としていた </編集>

この日のほかの記事

2026-09-27