10

私たちは皆、移植可能な C/C++ プログラムのファンです。

私たちはそれを知っているsizeof(char)sizeof(unsigned char)、常に1「バイト」です。しかし、その1「バイト」は8ビットのバイトを意味するものではありません。これは単に「マシン バイト」を意味し、その中のビット数はマシンごとに異なる場合があります。この質問を参照してください。


ASCII 文字 'A' をファイルに書き出すとしますfoo.txt。最近の 8 ビット マシン バイトを持つ通常のマシンでは、これらのビットが書き出されます。

01000001

しかし、マシンバイトが 9 ビットのマシンで同じコードを実行すると、これらのビットが書き出されると思います。

001000001

さらに重要なことに、後者のマシンは、これらの 9 ビットを 1 つのマシン バイトとして書き出すことができます。

100000000

しかし、以前のマシンでこのデータを読み取ろうとすると、十分なスペースがないため、適切に読み取ることができません。どういうわけか、最初に 1 マシン バイト (8 ビット) を読み取ってから、何らかの方法で最後の 1 ビットを 8 ビット (マシン バイト) に変換する必要があります。


プログラマーはこれらのことをどのように適切に調整できますか?

私が尋ねる理由は、ファイルを読み書きするプログラムがあり、5 年後、10 年後、50 年後も壊れないようにしたいからです。

4

9 に答える 9

7

プログラマーはこれらのことをどのように適切に調整できますか?

何もしないことによって。ファイルシステムの問題を提示しました。

多くの 9 ビット マシンの最初のマシンが起動し、コードを再コンパイルしてA、昨年ファイルに書き込んだ ASCII 文字を処理する準備が整ったあの恐ろしい日を想像してみてください。

C/C++ コンパイラがこのマシンに適切に存在できるようにするために、この新しいコンピュータの OS は、C および C++ が想定しているのと同じ標準に従います。ファイルのサイズはバイト単位で測定されます。

...8 ビット ソース コードには、すでに少し問題があります。各ソース ファイルがこのシステムに存在できるサイズである確率は、9 分の 1 程度です。

またはそうでないかもしれません。私にはよくあることですが、Johannes Schaub -litbはC++ ソース コードの有効なフォーマットに関する標準を先制的に引用しました。

物理的なソース ファイルの文字は、必要に応じて実装定義の方法で基本的なソース文字セットにマップされます (行末インジケーターに改行文字を導入します)。Trigraph シーケンス (2.3) は、対応する単一文字の内部表現に置き換えられます。基本ソース文字セット (2.2) にないソースファイル文字は、その文字を指定するユニバーサル文字名に置き換えられます。(実装では、ソース ファイルで実際の拡張文字が検出され、ソース ファイルでユニバーサル文字名として (つまり \uXXXX 表記を使用して) 表現された同じ拡張文字が処理される限り、任意の内部エンコーディングを使用できます。同等です。)

「実装定義の方法で。」これは朗報です...ソース コードをこのマシンで表現できる任意の 1:1 形式に変換する方法が存在する限り、それをコンパイルしてプログラムを実行できます。

だからここにあなたの本当の問題があります。このコンピューターの作成者が親切にも 8 ビット ASCII ファイルをビット拡張するユーティリティを提供して、実際にこの新しいマシンに保存できるようにした場合、Aあなたがずっと前に書いた ASCII 文字にはすでに問題はありません。そして、そのようなユーティリティがない場合、プログラムはすでにメンテナンスが必要であり、それを防ぐためにできることは何もありません。

編集:短い答え(その後削除されたコメントへの対処)

質問は、特定の9 ビット コンピューターをどのように扱うかを尋ねます...

  • 下位互換性のある 8 ビット命令を持たないハードウェアの場合
  • 「8ビットファイル」を使用しないオペレーティングシステム。
  • C/C++ プログラムが歴史的にテキスト ファイルを書き込んできた方法を打破する C/C++ コンパイラを使用します。

Damian Conwayは、C++ と C を比較して、しばしば繰り返される引用を持っています。

「C++ は、マキャベリではなく、マーフィーを防ごうとします。」

彼はハードウェア エンジニアではなく、他のソフトウェア エンジニアについて説明していましたが、理由は同じであるため、その意図は依然として健全です。

C と C++ はどちらも標準化されており、他のエンジニアがうまくやりたがっていると推測する必要があります。あなたのマキャヴェリアン コンピューターは、C/C++ 全体に対する脅威であるため、プログラムに対する脅威ではありません。

あなたの質問に戻ります:

プログラマーはこれらのことをどのように適切に調整できますか?

選択肢は 2 つあります。

  • あなたが記述したコンピューターが C/C++ の世界では適切ではないことを受け入れてください
  • C/C++ は、記述したコンピューターで実行される可能性のあるプログラムには適していないことを受け入れる
于 2013-01-20T18:49:44.207 に答える
3

確実にする唯一の方法は、データをテキストファイルに保存することです。数値は、ビット数ではなく、数値文字列として格納されます。UTF-8とbase10を使用するXMLは、明確に定義されているため、移植性と可読性の全体的な選択肢としてはかなり適切です。妄想的になりたい場合は、XMLを十分に単純にしてください。これにより、架空のコンピューターで実際のXMLパーサーをすぐに利用できない場合に備えて、簡単なカスタムパーサーで簡単に解析できるようになります。

数値を解析するとき、それが数値データ型に適合するものよりも大きい場合、それは、コンテキストに適合すると思われる場合に処理する必要のあるエラー状況です。または、「big int」ライブラリを使用します。これにより、任意の大きな数を処理できます(もちろん、「ネイティブ」数値データ型と比較して、パフォーマンスが1桁低下します)。

ビットフィールドを格納する必要がある場合は、ビットフィールド、つまりビット数を格納してから、任意の形式のビット値を格納します。

特定の数値範囲がある場合は、その範囲を格納して、使用可能な数値データ型に適合するかどうかを明示的に確認できるようにします。

バイトはかなり基本的なデータ単位であるため、ビット数の異なるストレージ間でバイナリデータを実際に転送することはできません。変換する必要があります。変換するには、データがどのようにフォーマットされているかを知る必要があります。そうしないと、マルチバイトを変換できません。正しく値します。

実際の答えを追加する:

  • Cコードでは、CPUアーキテクチャに応じて変更する分離関数を除いて、バイトバッファを処理しないでください。たとえば、.JPEG処理関数は、不特定の方法で画像データをラップする構造体、または画像を読み取るためのファイル名のいずれかを取りますが、rawchar*からバイトへのバッファは取りません。
  • エンコーディングを想定しないコンテナで文字列をラップします(おそらく、8ビットバイトマシンではUTF-8またはUTF-16を使用し、9ビットバイトマシンでは現在非標準のUTF-9またはUTF-18を使用する可能性があります) 。
  • 外部ソース(ネットワーク、ディスクファイルなど)からのすべての読み取りを、ネイティブデータを返す関数にラップします。
  • 整数のオーバーフローが発生しないコードを作成し、どのアルゴリズムでもオーバーフローの動作に依存しないでください。
  • (または何か~0の代わりに)を使用してオールワンビットマスクを定義する0xFFFFFFFF
  • 整数が不要なほとんどの数値ストレージでは、CPUアーキテクチャに依存しないため、IEEE浮動小数点数を優先します。
  • 変換が必要になる可能性のあるバイナリファイルに永続データを保存しないでください。代わりに、UTF-8でXMLを使用し(ネイティブ処理のために、何も壊さずにUTF-Xに変換できます)、XMLにテキストとして数値を格納します。
  • 異なるバイトオーダーの場合と同じですが、それ以上のことを除いて、確実な唯一の方法は、プログラムを異なるビット数の実際のマシンに移植し、包括的なテストを実行することです。これが本当に重要な場合は、最初にそのような仮想マシンを実装し、他に見つからない場合は、Cコンパイラとそれに必要なライブラリを移植する必要があります。注意深い(=高価な)コードレビューでさえ、あなたを途中でしか連れて行かないでしょう。
于 2013-01-18T16:58:39.207 に答える
2

1 つ目:移植性の本来の実際的な目標は、作業を減らすことです。したがって、同じ最終結果を得るために移植性が非移植性よりも多くの労力を必要とする場合、そのような場合に移植可能なコードを書くことはもはや有利ではありません。原則から単純に「移植性」を目標にしないでください。あなたの場合、ディスクフォーマットに関する十分に文書化されたメモを備えた非ポータブルバージョンは、将来の保証のより効率的な手段です. 潜在的な一般的なストレージ形式に何らかの形で対応するコードを書こうとすると、おそらくコードがほとんど理解できないものになるか、その理由で支持されなくなることを維持するのが面倒になります (誰も望んでいない場合は、将来の証明について心配する必要はありません)。とにかく今から20年後にそれを使用するために)。

2 つ目: これについて心配する必要はないと思います。なぜなら、9 ビット マシン (または同様のマシン) で 8 ビット プログラムを実行する唯一の現実的な解決策は、仮想マシンを使用することだからです。

近い将来または遠い将来、一部の 9 ビット以上のマシンを使用する人が、従来の x86/arm 仮想マシンを起動して、その方法でプログラムを実行できるようになる可能性が非常に高くなります。今から 25 年から 50 年後のハードウェアでは、単一のプログラムを実行するためだけに仮想マシン全体を実行しても、まったく問題はないはずです。そして、そのプログラムは、現在のネイティブ 8 ビット ハードウェアで現在よりも高速にロード、実行、およびシャットダウンする可能性があります。 (実際、今日の一部のクラウド サービスでは、個々のタスクにサービスを提供するためだけに VM 全体を開始する傾向が既にあります)

8ビットソースコードを単純にロードして解析することに固有の基本的な課題に関する他の回答で指摘されているため、これが8ビットプログラムを9/その他のビットマシンで実行する唯一の手段であると強く疑っています。8 ビットのバイナリ実行可能ファイル。

「効率的」とは少し似ていないかもしれませんが、うまくいくでしょう。これはもちろん、仮想ディスクからホスト ディスクに 8 ビットのテキスト ファイルをインポートおよびエクスポートできる何らかのメカニズムが VM にあることも前提としています。

ただし、ご覧のとおり、これはソース コードをはるかに超えた大きな問題です。肝心なのは、ほとんどの場合、新しいハードウェアでプログラムを更新/変更したり、ゼロから再実装したりする方が、そのようなあいまいな移植性の問題を説明しようとするよりも、はるかに安価で簡単になるということです。フロント。これを考慮する作業には、ディスク フォーマットを変換するだけでなく、より多くの労力が必要になることはほぼ確実です。

于 2013-01-21T00:48:15.780 に答える
2

量子コンピューター (近い将来購入できるようになる予定です) 用のプログラムを作成する予定がある場合は、量子物理学の学習を開始し、プログラミングのクラスに参加してください。

近い将来にブール型のコンピューター ロジックを計画している場合を除き、私の質問は、今日利用可能なファイル システムが明日と同じではないことをどのように確認するかということです。または、8 ビット バイナリで保存されたファイルが、将来のファイル システムでどのように移植性を維持するのでしょうか?

何世代にもわたってプログラムを実行し続けたい場合は、独自のファイルシステムとオペレーティングシステムを備えた独自のコンピューティングマシンを作成し、将来のニーズの変化に応じてインターフェイスを変更することをお勧めします.

私の問題は、私が数年前にプログラムしたコンピューター システム (Motorola 68000) が一般に公開されておらず、そのプログラムがマシンのバイト オーダーとアセンブリ言語に大きく依存していたことです。もう移植できません:-(

于 2013-01-18T12:38:28.007 に答える
2

バイナリデータの書き込みと読み取りについて話している場合は、気にしないでください。現在、プログラムから書き込んだデータが、同じコンパイラ (コマンドライン設定を含む)でコンパイルされた同じプログラムで読み取れることを除いて、移植性の保証はありません。テキストデータの書き込みと読み取りについて話している場合でも、心配する必要はありません。できます。

于 2013-01-18T14:05:27.910 に答える
1

8 ビット バイトは最後まで残りますので、気にしないでください。新しいタイプがありますが、この基本的なタイプは決して変わることはありません。

于 2013-01-18T12:29:33.787 に答える
1

ちょっと遅いですが、これに抵抗することはできません。未来を予測するのは難しい。コンピューターの未来を予測することは、時期尚早の最適化よりも、コードにとってより危険な場合があります。

簡単な回答
9 ビット システムが 8 ビット バイトの移植性をどのように処理したかでこの記事を締めくくりますが、この経験から、9 ビット バイト システムが汎用コンピューターに再び登場することはないと信じています。

私の予想では、将来の移植性の問題は、CHAR_BIT を少なくとも 16 にする、最低 16 ビットまたは 32 ビット アクセスを持つハードウェアで発生することです。ここでの注意深い設計は、予期しない 9 ビット バイトに役立つ可能性があります。

/への質問読者: 9 ビット バイトまたは 1 の補数演算を使用して、現在生産されている汎用 CPU を知っている人はいますか? 組み込みコントローラーが存在する可能性がある場所はわかりますが、他にはあまりありません。

長い回答
1990 年代のコンピューターのグローバル化と Unicode により、UTF-16 またはそれ以上の文字あたりのビット数 (C の CHAR_BIT) の拡張を推進することを期待するようになりました。少なくともコンピュータがバイナリを使用している限り、業界標準のままです。

BYTE_BIT: 1 バイトあたりのビット数 (一般的ですが、私が知っている標準ではありません)
BYTE_CHAR: 1 文字あたりのバイト数

C 標準は、複数バイトを消費するcharに対応していません。それはそれを可能にしますが、それに対処しません。

3.6 バイト: (最終草案C11 標準 ISO/IEC 9899:201x )
実行環境の基本文字セットの任意のメンバーを保持するのに十分な大きさのデータ ストレージのアドレス可能な単位。

注 1: オブジェクトの個々のバイトのアドレスを一意に表すことができます。

注 2: 1 バイトは連続したビットのシーケンスで構成され、その数は実装定義です。最下位ビットは下位ビットと呼ばれます。最上位ビットは上位ビットと呼ばれます。

C 標準が 1 より大きい BYTE_CHAR 値を処理する方法を定義するまで、そして私は「ワイド文字」について話していませんが、移植可能なコードの主要な要素はこれに対処する必要があり、より大きなバイトではありません。CHAR_BIT が 16 または 32 である既存の環境を検討する必要があります。ARM プロセッサはその一例です。開発者が選択する必要がある外部バイト ストリームを読み取るための 2 つの基本モードが表示されます。

  • アンパック: 1 つの BYTE_BIT 文字をローカル文字に。符号の延長に注意してください。
  • Packed: BYTE_CHAR バイトをローカル文字に読み取ります。

移植可能なプログラムには、バイトの問題に対処する API レイヤーが必要になる場合があります。その場でアイデアを作成するために、私は将来攻撃する権利を留保します。

  #define BYTE_BIT 8 // バイトあたりのビット数
  #define BYTE_CHAR (CHAR_BIT/BYTE_BIT) //文字あたりのバイト数

  size_t byread(void *ptr,
                size_t size, // BYTE_BIT バイト数
                int パッキング、// 文字ごとに読み取るバイト数
                                 // (符号拡張の場合は負)
                FILE *ストリーム);

  size_t bywrite(void *ptr,
                size_t サイズ、
                イントパッキング、
                FILE *ストリーム);
  • sizenumber BYTE_BIT バイトを転送します。
  • packingchar文字ごとに転送するバイト数。通常は 1 または BYTE_CHAR ですが、外部システムの BYTE_CHAR を示している可能性があり、現在のシステムよりも小さい場合も大きい場合もあります。
  • エンディアンの衝突を決して忘れないでください。

9 ビット システムへのよき皮肉:
9 ビット環境用のプログラムを書いた以前の経験から、どこかで実際に古いレガシー システムで実行するプログラムがたまたま必要でない限り、そのようなものは二度と見られないと思います。32/64 ビット システムの9 ビット VMで発生する可能性があります。2000 年以来、古い 9 ビット システムの現在の子孫への参照を時々手早く検索しますが、見たことはありません。

私の見解では非常に予想外ですが、将来の汎用 9 ビット コンピュータには、プログラムを実行するための 8 ビット モードまたは 8 ビット VM (@jstine) が搭載される可能性があります。唯一の例外は、汎用コードがとにかく実行される可能性が低い特別な目的で構築された組み込みプロセッサです。

昔は、9 ビット マシンの 1 つに PDP/15 がありました。この獣のクローンとの 10 年間の闘いから、9 ビット システムが再び登場することは決して期待できません。理由についての私のトップピックは次のとおりです。

  • 余分なデータ ビットは、コア メモリ内のパリティ ビットを奪ったものです。古い 8 ビット コアには、隠しパリティ ビットが含まれていました。どのメーカーもそうでした。コアが十分に信頼できるようになると、一部のシステム設計者は既存のパリティをデータビットに切り替えて、MMU 以外の弱いマシンの時代にもう少し数値パワーとメモリアドレスを得るために簡単な策略を講じました。現在のメモリ技術にはそのようなパリティ ビットはなく、マシンはそれほど弱くなく、64 ビット メモリは非常に大きいです。これらすべてが、当時の変更よりも設計変更の費用対効果を低下させるはずです。
  • 他のシステムだけでなく、既製のローカル I/O デバイスを含む 8 ビット アーキテクチャと 9 ビット アーキテクチャの間でデータを転送することは、継続的な苦痛でした。同じシステム上の異なるコントローラーが互換性のない手法を使用しました:
    1. 18 ビット ワードの下位 16 ビットを使用します。
    2. 9 ビット バイトの下位 8 ビットを使用します。余分な上位ビットは、パリティに敏感なデバイスから読み取られたバイトのパリティに設定される可能性があります。
    3. 3 つの 8 ビット バイトの下位 6 ビットを組み合わせて、18 ビットのバイナリ ワードを作成します。
    一部のコントローラでは、実行時に 18 ビットと 16 ビットのデータ転送を選択できました。将来のハードウェアやサポートするシステム コールがどのようなものになるかは、事前に予測することはできません。
  • 8 ビットのインターネットに接続すること自体が恐ろしいことで、誰かが持つ 9 ビットの夢を台無しにしてしまいます。当時はマシンが相互接続されていなかったので、彼らはそれを回避しました。
  • バイトアドレスのストレージに 2 ビットの偶数倍以外のものがあると、あらゆる種類の問題が発生します。例: 8 ビット バイトで数千ビットの配列が必要な場合は、unsigned char bits[1024] = { 0 }; bits[n>>3] |= 1 << (n&7);. 9 ビットを完全にパックするには、実際の除算を行う必要があり、パフォーマンスが大幅に低下します。これはワードあたりのバイト数にも当てはまります。
  • 9 ビット バイト ハードウェアで実際にテストされていないコードは、予想外の 9 ビット バイトの世界への最初の実際の冒険で失敗する可能性があります。 . 前の byread()/bywrite() がここで役立つかもしれませんが、転送モードを設定するために追加の CHAR_BIT モード設定が必要になる可能性が高く、現在のコントローラーが要求されたバイトをどのように配置するかを返します。

完全に言うと、教育経験のために 9 ビット バイトについて心配したい人は、自分の補体系が戻ってくることについても心配する必要があるかもしれません。当然の死を遂げたと思われる何か他のもの (2 つのゼロ: +0 と -0 は進行中の悪夢の原因です... 信じてください)。当時の 9 ビット システムは、多くの場合、1 の補数演算と対になっているように見えました。

于 2013-01-21T09:17:49.357 に答える
1

将来のコンピューターで非 8 ビット バイトが使用される可能性は低いと思います。それは非常に多くの書き直しを必要とし、ほとんどメリットがありません。でもそうなったら…

すべての計算をネイティブ データ型で行い、入力を書き換えるだけで、多くの問題を解決できます。私は次のようなものを描いています:

template<int OUTPUTBITS, typename CALLABLE>
class converter {
  converter(int inputbits, CALLABLE datasource);
  smallestTypeWithAtLeast<OUTPUTBITS> get();
};

これは将来、そのようなマシンが存在するときに書き込むことができるため、今は何もする必要がないことに注意してください。または、本当に偏執的である場合は、OUTPUTBUTS==inputbits のときに get が datasource を呼び出すようにしてください。

于 2013-01-23T18:46:47.253 に答える
-1

プログラミング言語では、1 バイトは常に 8 ビットです。そのため、あるマシンでバイト表現が 9 ビットの場合、何らかの理由でそれを調整するのは C コンパイラ次第です。char を使用してテキストを書き込む限り、たとえば、「A」をファイルに書き込み/読み取る場合、ファイルには 8 ビットのみを書き込み/読み取ることになります。したがって、問題はないはずです。

于 2013-01-24T04:12:13.860 に答える