どのプラットフォームに8ビット文字以外のものがありますか?


136

時々、SOの誰かがchar(別名「バイト」)が必ずしも8ビットではないことを指摘します

8ビットcharはほとんど普遍的なもののようです。主流のプラットフォームではchar、市場での実行可能性を確保するために8ビットが必要であると私は思っていました。

現在と歴史の両方で、どのプラットフォームcharが8ビットではないを使用していますか?なぜそれらが「通常の」8ビットと異なるのですか?

コードを記述し、クロスプラットフォームサポート(たとえば、汎用ライブラリ)について考えるとき、8ビット以外のプラットフォームにどのような考慮を払う価値がありますcharか?

過去に、char16ビットのAnalog Devices DSPに出くわしました。DSPは、私が想定しているニッチなアーキテクチャのビットです。(そして、当時、手動でコード化されたアセンブラーは、利用可能なCコンパイラーができることを簡単に打ち負かしたので、そのプラットフォームでのCの経験はあまりありませんでした。)


9
CDC Cyber​​シリーズには6/12ビットのエンコーディングがありました。最も人気のある文字は6ビットでした。残りの文字は12ビットを使用しました。
Thomas Matthews

2
PDP-11はそれを釘付けにしました。文字をcharにエンコードできるという概念は、かなり時代遅れです。
ハンスパッサント2010年

7
「PDP-11はそれを釘付けにしました」-Cが最初に8ビットバイトでPDP-11に実装されたからですか?しかし、Cは次に、9ビットバイトのHoneywellマシンに実装されました。K&Rバージョン1を参照してください。また、質問は文字(質問されなかったものをエンコードする1つ以上のバイト)ではなく、文字(バイト)について質問されました。
Windowsプログラマ、

6
DEC-10とDEC-20には36ビットのワードがありました。単語ごとに5つの7ビットASCII文字が一般的でした。また、6ビットの6文字が使用されました。
デビッドRトリブル

3
@CraigMcQueen:私が正しく覚えている場合、Atmelマイクロコントローラー用のCodeVisionでは、charのサイズを選択できます
vsz

回答:


80

charTexas Instruments C54x DSPでも16ビットで、たとえばOMAP2で表示されます。他にも16ビットと32ビットのDSPがありますchar。24ビットDSPについて聞いたこともあると思いますが、何を覚えているかわからないので、想像してみました。

もう1つの考慮事項は、POSIXが義務付けていることCHAR_BIT == 8です。したがって、POSIXを使用している場合は、それを想定できます。誰かが後でコードをPOSIXに近い実装に移植する必要がある場合、たまたま使用する関数が異なるサイズになりますがchar、それは彼らの不運です。

しかし、一般的には、問題を回避する方が、考えるよりも、ほとんど常に簡単だと思います。入力するだけですCHAR_BIT。正確な8ビットタイプが必要な場合は、を使用しますint8_t。コードは、予期しないサイズを暗黙的に使用するのではなく、コードを提供しない実装で騒々しくコンパイルできなくなります。少なくとも、私がそれを仮定する正当な理由がある場合に当たれば、私はそれを断言するでしょう。


2
TI C62xxおよびC64xx DSPにも16ビット文字があります。(uint8_tはそのプラットフォームでは定義されていません。)
myron-semack

7
オーディオ処理用のDSPの多くは24ビットマシンです。BelaSignaセミ上からのDSP(彼らはAMI半を買った後)。Freescale のDSP56K / Symphony Audio DSP(Motorolaから分離された後)。
David Cary

2
@msemack C64xxには、8
/

4
むしろよりassert()(それはあなたが何を意味するかの場合)、私が使用したい#if CHAR_BIT != 8... #error "I require CHAR_BIT == 8"...#endif
キース・トンプソン

1
@KeithThompson使用しない理由はありますstatic_assert()か?
Qix-モニカは2017

37

コードを記述し、クロスプラットフォームサポート(たとえば、汎用ライブラリ)について考えるとき、8ビット以外の文字を使用するプラットフォームにどのような考慮が必要ですか?

ルールで遊んでいるので、何かを「考慮する価値がある」ほどではありません。たとえば、C ++では、すべてのバイトに「少なくとも」8ビットが含まれると標準で規定されています。バイトが正確に8ビットであるとコードが想定している場合は、標準に違反しています。

これは今ではばかげているように見えるかもしれません-「もちろん、すべてのバイトは8ビットです!」しかし、多くの非常に賢い人々は、保証ではない仮定に依存しており、それからすべてが壊れました。歴史はそのような例でいっぱいです。

たとえば、ほとんどの90年代初頭の開発者は、ほとんどのコンシューマCPUの電力はほぼ同等であるため、特定の何もしないCPUタイミング遅延が一定のサイクル数を取ると、固定量のクロック時間がかかると想定していました。残念ながら、コンピューターの速度は非常に速くなりました。これにより、「ターボ」ボタンが付いたボックスが登場しました。皮肉なことに、その目的はコンピューターをスローダウンして、時間遅延技術を使用したゲームを妥当な速度でプレイできるようにすることでした。


あるコメンターは、標準のどこにcharは少なくとも8ビットでなければならない、と言っています。セクション5.2.4.2.1にあります。このセクションではCHAR_BIT、アドレス指定可能な最小のエンティティのビット数を定義し、デフォルト値は8です。

それらの実装定義の値は、表示されている値と同じ符号で、絶対値(絶対値)以上でなければなりません。

したがって、8以上の任意の数は、への実装による置換に適していCHAR_BITます。


6
ターボボタンは20年以上見たことがありません。この質問に密接に関係していると思いますか。
Mark Ransom、2010年

29
@Mark Ransom:それがポイントです。開発者は、現時点では真実であるように見えるが、最初に表示されるよりもはるかに不安定な仮定に依存することがよくあります。(私がその間違い犯した回数を数えることはできません!)ターボボタンは、不必要な仮定を行わないように、そして言語標準によって保証されていないような仮定を行わないようにするための苦痛なリマインダである必要があります。不変の事実。
John Feminella、2010年

1
さようなら少なくとも8ビットがあると言っているC ++標準に置くことを指摘できますか?それは一般的な信念ですが、私は個人的には規格でそれを見つけることができませんでした。私が標準で見つけた唯一のことは、どの文字charが64を超えて表現可能でなければならないかということですが、128未満なので、7ビットで十分です。
Adam Badura、2010年

6
セクション18.2.2は、C標準を呼び出します。C標準では、セクション7.10で、次にセクション5.4.2.4.1です。C標準の22ページ。
Windowsプログラマ

2
したがって、他の回答やコメントでは、5ビット、6ビット、7ビットバイトのマシンについて言及しています。それは、標準に準拠するそのマシン上でCプログラムを実行できないことを意味しますか?
ジェリージェレミア

34

36ビットアーキテクチャのマシンには9ビットバイトがあります。Wikipediaによると、36ビットアーキテクチャのマシンには次のものが含まれます。

  • デジタル機器株式会社PDP-6 / 10
  • IBM 701/704/709/7090/7094
  • UNIVAC 1103 / 1103A / 1105/1100/2200、

7
Cが実装された2番目のマシンなどのHoneywellマシン。K&Rバージョン1を参照してください
Windowsのプログラマ

5
実際、12月-10はまた、6ビットの文字を持っていた-あなたは、36ビット・ワード(EX-12月- 10プログラマの話)にこれらの6を詰めることができ

2
DEC-20では、TOPS-20 O / Sで36ビットワードあたり5つの7ビットASCII文字を使用していました。
David R Tribble

3
そのジョークは、このアーキテクチャでUnicodeをサポートするために実際に実装されました。
Joshua

9
8進数が実際に使用された理由は、2つの16進数が8ビットのバイトをきちんと表すため、今日通常16進数を使用するのと同じように、3つの8進数が9ビットのバイトをきちんと表すためだと思います。
bames53 2012

18

私が知っているもののいくつか:

  • DEC PDP-10:可変ですが、ほとんどの場合、7ビット文字は36ビットワードごとに5つパックされます。そうでなければ、9ビット文字、ワードごとに4つパックされます。
  • コントロールデータメインフレーム(CDC-6400、6500、6600、7600、Cyber​​ 170、Cyber​​ 176など)6ビット文字、60ビットワードごとに10個パック。
  • Unisysメインフレーム:9ビット/バイト
  • Windows CE:単に `char`タイプをまったくサポートしていません-代わりに16ビットのwchar_tが必要です

2
@ephemient:私かなり確信してPDP-10 / DecSystem 10 / DecSystem 20のための少なくとも1つ(プリ標準)Cコンパイラがあったんだ、私はするだろう非常に(彼らがいたのにCDCのメインフレーム用のCコンパイラに驚き主に数値計算に使用されるため、Fortranコンパイラが大きな役割を果たしました)。他の人がCコンパイラを持っていると確信しています。
Jerry Coffin

3
Windows CEコンパイラは本当にそのchar型をまったくサポートしていませんでしたか?システムライブラリは文字列を使用する関数のワイド文字バージョンのみをサポートし、WinCEの少なくとも一部のバージョンは文字列処理を停止するためにstrlenなどのANSI文字列関数を削除したことを知っています。しかし、実際にはchar型はまったくありませんでしたか?なにsizeof(TCHAR)?mallocはどのタイプを返しましたか?Java byteタイプはどのように実装されましたか?
スティーブジェソップ

10
Windows CEは、バイトであるcharをサポートします。Richard Penningtonの回答に関するCraig McQueenのコメントを参照してください。Windows CEでは、バイト数は、他の場所のサイズに関係なく、他の場所と同じくらい必要です。
Windowsプログラマ

2
PDP-10用のCの実装には、少なくとも2つあります(KCCとgccのポート(pdp10.nocrew.org/gcc))。
AProgrammer 2010年

3
C標準では、36ビットワードごとに5つパックされた7ビット文字(PDP-10について述べたように)は許可されません。また、コントロールデータメインフレームについて述べたように、6ビット文字も許可されません。parashift.com/c++-faq-lite/intrinsic-types.html#faq-26.6
Ken Bloomを

15

完全に移植可能なコードなどはありません。:-)

はい、バイト/文字のサイズはさまざまです。はい、非常に変わった値のCHAR_BITおよびを持つプラットフォーム用のC / C ++実装がある場合がありUCHAR_MAXます。はい、時々文字サイズに依存しないコードを書くことが可能です。

ただし、ほとんどすべての実際のコードはスタンドアロンではありません。たとえば、バイナリメッセージをネットワークに送信するコードを記述している可能性があります(プロトコルは重要ではありません)。必要なフィールドを含む構造を定義できます。それをシリアル化する必要があるよりも。構造体を出力バッファーにバイナリコピーするだけでは移植性がありません。通常、プラットフォームのバイトオーダーも構造体メンバーの配置もわからないため、構造体はデータを保持するだけで、データのシリアル化方法については説明しません。

OK。バイト順変換を実行し、構造体のメンバー(uint32_tまたは類似のもの)を使用memcpyしてバッファーに移動できます。なんでmemcpy?ターゲットアドレスが適切に配置されていない場合、32ビット(16ビット、64ビット、違いはありません)を書き込むことができないプラットフォームがたくさんあるためです。

したがって、移植性を実現するためにすでに多くのことを行っています。

そして最後の質問です。バッファがあります。そこからのデータはTCP / IPネットワークに送信されます。このようなネットワークは、8ビットバイトを想定しています。問題は、バッファのタイプをどうするかです。あなたの文字が9ビットなら?16ビットの場合はどうでしょうか。24?たぶん、各文字はネットワークに送信される1つの8ビットバイトに対応し、8ビットのみが使用されますか?それとも、複数のネットワークバイトが24/16/9ビット文字にパックされているのでしょうか?それは問題であり、すべてのケースに当てはまる単一の答えがあるとは信じがたいです。多くのことは、ターゲットプラットフォームのソケット実装に依存しています。

だから、私が話していること。通常、コードはある程度簡単に移植できます。別のプラットフォームでコードを使用する場合は、そうすることが非常に重要です。ただし、実際のコードはほとんど常に他のコード(上記の例のソケット実装)に依存しているため、この方法を超えて移植性を向上させることは、多くの労力を必要とし、多くの場合ほとんど効果がありません。8ビットにバインドされた環境を使用するため、8ビット以外のバイトを使用するプラットフォームで機能するコード機能の約90%はほとんど役に立たないと私は確信しています。バイトサイズを確認し、コンパイル時間のアサーションを実行するだけです。非常に珍しいプラットフォームでは、ほぼ確実に多くのことを書き直す必要があります。

しかし、コードが高度に「スタンドアロン」である場合は、なぜでしょうか。異なるバイトサイズを許可する方法でそれを書くかもしれません。


4
unsigned char値ごとに1オクテットを格納する場合、コードがシフトではなくエイリアシングトリックを使用してオクテットのシーケンスをより大きな整数型との間で変換しない限り、移植性の問題はありません。個人的には、C標準は組み込みの組み込み関数を定義して、短いタイプ(最も一般的にはchar)のシーケンスから整数をパック/アンパックして、アイテムごとに保証された利用可能な固定ビット数(8あたりunsigned char、16あたりunsigned short、または32あたりunsigned long)を格納する必要があると思います。
スーパーキャット2015



5

たとえば、CおよびC ++プログラミング言語は、バイトを「実行環境の基本文字セットのメンバーを保持するのに十分な大きさのアドレス可能なデータの単位」(C標準の3.6節)として定義します。C char整数データ型には少なくとも8ビットが含まれている必要があるため(5.2.4.2.1節)、Cのバイトは少なくとも256の異なる値を保持できます。CおよびC ++のさまざまな実装では、バイトを8、9、16、32、または36ビットとして定義します

http://en.wikipedia.org/wiki/Byte#Historyからの引用

他の言語についてはわかりません。

http://en.wikipedia.org/wiki/IBM_7030_Stretch#Data_Formats

そのマシンのバイトを可変長に定義します


1
「他の言語についてはわかりません」-歴史的に、ほとんどの言語では、マシンのアーキテクチャで独自のバイトサイズを定義できました。実は歴史的にそうCは、標準セットまで下8に結合しなかった
Windowsのプログラマー

4

DEC PDP-8ファミリには12ビットワードがありましたが、通常は出力に8ビットASCIIを使用しました(ほとんどのテレタイプでは)。ただし、1つの12ビットワードに2文字をエンコードできる6ビット文字コードもありました。


3

1つは、Unicode文字が8ビットより長いことです。先に述べたように、C仕様ではデータ型を最小サイズで定義しています。データ型を調べて、構成とアーキテクチャーのデータサイズを正確に調べる場合sizeofは、との値を使用limits.hします。

このため、uint16_t特定のビット長のデータ型が必要なときなどに、データ型にこだわるようにしています。

編集:申し訳ありませんが、私は最初にあなたの質問を誤解しました。

C仕様によると、charオブジェクトは「実行文字セットのメンバーを格納するのに十分な大きさ」です。 limits.hは8ビットの最小サイズをリストしていますが、定義はcharオープンの最大サイズを残しています。

したがって、a charは少なくとも、アーキテクチャの実行セットの最大の文字(通常、最も近い8ビット境界に切り上げられる)と同じ長さです。アーキテクチャのオペコードが長い場合、charサイズが長くなる可能性があります。

歴史的に、x86プラットフォームのオペコードは1バイト長charでしたので、最初は8ビット値でした。現在のx86プラットフォームは1バイトより長いオペコードをサポートしますが、charプログラマー(および既存のx86コードの大容量)が条件付けするものであるため、長さは8ビットに保たれます。

マルチプラットフォームのサポートについて考えるときは、で定義されているタイプを活用してくださいstdint.h。あなたが(例えば)uint16_tを使用する場合は、16ビットの値に相当するものかどうか、この値は、どのようなアーキテクチャ上の符号なし16ビット値であることを確認することができcharshortint他の、または何か。困難な作業のほとんどは、コンパイラ/標準ライブラリを作成した人々によってすでに行われています。

を必要とするchar低レベルのハードウェア操作を行っているためにaの正確なサイズを知る必要がある場合、私は通常、charサポートされているすべてのプラットフォームで(通常は16ビットで十分です)を保持するのに十分な大きさのデータ型を使用して実行します。convert_to_machine_char正確なマシン表現が必要な場合のルーチンによる値。そうすれば、プラットフォーム固有のコードはインターフェース関数に限定され、ほとんどの場合、通常のを使用できますuint16_t


2
この質問では、文字(Unicodeかどうか)については尋ねられませんでした。それはバイトであるcharについて尋ねました。
Windowsプログラマ

1
また、実行文字セットはオペコードとは関係ありません。実行時に使用される文字セットです。クロスコンパイラと考えてください。
ninjalj 2010

「歴史的に、x86プラットフォームのオペコードは1バイト長でした」:なんて甘いのでしょう。 歴史的に、CはPDP-11(1972)で開発され、x86が発明される(1978)よりずっと前に。
Martin Bonnerはモニカ

3

8ビット以外の文字を使用するプラットフォームにはどのような考慮事項がありますか?

マジックナンバーは、例えばシフト時に発生します。

これらのほとんどは、CHAR_BITや、8や255(または同様のもの)の代わりにUCHAR_MAXを使用することで、非常に簡単に処理できます。

うまくいけば、あなたの実装はそれらを定義します:)

それらは「一般的な」問題です.....

別の間接的な問題は、あなたが持っていると言うことです:

struct xyz {
   uchar baz;
   uchar blah;
   uchar buzz; 
}

これは、1つのプラットフォームで(最善の場合)24ビットを取るだけですが、他の場所ではたとえば72ビットかかる可能性があります。

各ucharが「ビットフラグ」を保持し、各ucharに現在使用している2つの「重要な」ビットまたはフラグしかなく、それらを「明確さ」のために3つのucharに編成した場合、比較的「より無駄」になる可能性があります。 24ビットucharを備えたプラットフォーム.....

ビットフィールドで解決できないものはありませんが、他にも注意する必要があるものがあります....

この場合、1つのenumだけで、実際に必要な「最小」サイズの整数を取得できます。

おそらく実際の例ではないかもしれませんが、このようなものは、コードを移植/再生するときに私に「ビット」を与えます。

ucharが「通常」予想されるものの3倍の大きさである場合、100のそのような構造は、一部のプラットフォームでは大量のメモリを浪費する可能性があるという事実だけです。 。

そのため、あるプラットフォームでは、利用可能なRAMと比較して、ucharは別のプラットフォームよりも「それほど無駄ではない」という仮定のため、物事はまだ「壊れている」可能性があります。 ..

問題は、たとえばintや他のタイプの場合にさらに顕著になる可能性があります。たとえば、15ビットを必要とする構造があるため、intに貼り付けますが、他のプラットフォームではintは48ビットなどです。 。

「通常」は2つのucharに分割する可能性がありますが、たとえば24ビットのucharでは1つだけ必要です。

したがって、列挙型の方が「一般的な」解決策になる可能性があります。

ただし、これらのビットにアクセスする方法によって異なります。

そのため、ucharやuintのサイズに関係なく、コードがまだ正常に動作する場合でも、「設計上の欠陥」が発生する可能性があります...

コードに「マジックナンバー」がなくても、このようなことに注意する必要があります...

これが理にかなっていると思います:)


1
...何?なぜenum他のネイティブ型よりも小さいと思われるのですか?デフォルトで同じストレージに設定されていることをご存知intですか?「あなたはint型でそれを固執するので、15ビットを必要とするいくつかの構造を有しているが、いくつかの他のプラットフォームでintが48ビットであるか、何でも.....」 -そう#include <cstdint>、それ作るint16_tビット使用量を最小限にする最高のチャンスのために。あなたがそれらのすべての楕円の中であなたが言っていたと思っていたことが本当にわかりません。
underscore_d

1

以前は16ビットであったint(pdp11など)。32ビットアーキテクチャに移行するのは困難でした。人々は良くなっています:ポインターがこれ以上長く収まるとは誰も想定していません(正しくありませんか?)。またはファイルのオフセット、またはタイムスタンプ、または...

8ビット文字はすでに多少時代遅れのものです。世界のすべての文字セットを保持するために、すでに32ビットが必要です。


2
そうだね。名前charは、Unicodeの時代には少し趣があります。ファイルストレージ、ネットワーク通信などのバイナリデータを処理するときは、8ビット単位(オクテット)についてもっと気にします。uint8_tより便利です。
Craig McQueen

3
実際には、Unicodeは完全な32ビットを必要としませんでした。当初は31を計画していましたが(元のUTF-8の作業を参照)、現在は21ビットのみのコンテンツです。彼らは実際にすべての31ビットが必要な場合、本をもう印刷できないことに気づいたでしょう:P
me22

2
@ me22、Unicodeは当初16ビットを計画していました。「Unicode文字は、言語に関係なく、一貫して16ビット幅です...」Unicode 1.0.0。unicode.org/versions/Unicode1.0.0/ch01.pdf
シャノン退職

1
ISO 10646は元々31ビットでしたが、UnicodeはISO 10646と統合されたので、Unicodeは31ビットであると言ったのはおかしいかもしれませんが、実際には正しくありません。実際には、完全なコード表をもう印刷しないことに注意してください。
プロフィラ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.