コンピューターは、「\ 0」(ヌル文字)と「unsigned int = 0」をどのように区別しますか?


29

特定の状況で、文字の配列(もちろんnull文字で終わる)があり、その直後にメモリの次の位置に0符号なしintとして格納する場合、コンピューターはこれらをどのように区別しますか二?


18
あなたは、答えが完全に正しい典型的なコンピューターについて尋ねています。ただし、データ型を区別するためにタグ付きメモリを使用するアーキテクチャがいくつかありました。
-grawity

12
コンピューターが4バイトの整数と4バイトの整数を区別できないのと同じ方法(非常に異なる数を表します)。
ハーゲンフォンアイゼン

6
文字列を0x00で終了するのが一般的ですが、長さの接頭辞付き文字列を使用する言語があります。最初の1〜2バイトには、文字列のバイト数が含まれます。このように、最後に0x00は必要ありません。PascalとBASICがそれを行ったことを思い出すようです。おそらくCOBOLも同様です。
点灯

@litは、多くの通信プロトコルのヘッダー形式でもあります。「こんにちは、私はこの種のメッセージであり、私はこの長さのバイトです」。多くの場合、複雑なデータ型を内部に保存する必要があるため、null終了は解析がはるかに面倒になります。
mathreadler

1
@lit:PascalとBASICのほとんどのバリエーション、およびPL / IとAda-および7u6で部分文字列共有が削除されたためJavaでは、配列長プレフィックスが効果的に使用されますが、COBOLのみsort-of:you can read from data pic X occurs m to n depending on v(カウントは直前だけでなくどこでも可能ですが、保存はより複雑です。
-dave_thompson_085

回答:


86

そうではありません。

文字列ターミネータは、すべて0ビットを含むバイトです。

unsigned intは2バイトまたは4バイト(環境に応じて)で、それぞれにすべて0ビットが含まれます。

2つのアイテムは異なるアドレスに保存されます。コンパイルされたコードは、前者の文字列に適した操作を実行し、後者の場所に符号なし2進数に適した操作を実行します。(コードにバグがあるか、または危険なほど巧妙なコードがない限り!)

ただし、これらのバイトはすべてCPUから見ると同じように見えます。メモリ内のデータ(現在最も一般的な命令セットアーキテクチャ)は、それに関連付けられた型を持ちません。これは、ソースコードにのみ存在する抽象化であり、コンパイラにとってのみ何かを意味します。

編集追加:例:文字列を構成するバイトに対して算術演算を実行することは完全に可能であり、一般的です。8ビットASCII文字のストリングがある場合、32(10進数)を加算または減算することにより、ストリング内の文字を大文字と小文字の間で変換できます。または、別の文字コードに変換する場合は、その値を、他のコードで同等のビットコーディングを提供する要素を持つ配列へのインデックスとして使用できます。

CPUにとって、文字は実際には非常に短い整数です。(16、32、または64ではなく、それぞれ8ビット。)人間にとって、それらの値はたまたま読み取り可能な文字に関連付けられていますが、CPUはそれを認識していません。また、「ヌルバイトが文字列を終了する」という「C」規約についても何も知りません(他の回答やコメントで指摘されているように、その規約がまったく使用されないプログラミング環境もあります) 。

確かに、x86 / x64には文字列(REPプレフィックスなど)で頻繁に使用される傾向があるいくつかの命令がありますが、希望する結果が得られれば、整数の配列でも同様に使用できます。


14
そのため、開発者は文字列に注意する必要があります。たとえば、100個の連続したバイトがある場合、最大99個の1バイト文字と最後のバイトのターミネータを収容できます。そこに100バイトの文字列を書き込むと、プログラムは文字列がそこで終わることを把握できず、偶然ゼロバイトになるまで連続したバイトの読み取りを続けます。文字列の長さが100バイトを超える場合、隣接するデータが上書きされます。高レベルのプログラミング言語(Java、C#、JSなど)がこれ自体を処理しますが、C、C ++、アセンブリなどの低レベルの言語では、開発者の責任です。
グローノスタジ

18
@gronostajコメントはやや混乱します。Cとは異なり、C ++の文字列もこれを自動的に処理します。また、C ++は一般に低レベル言語として分類されません(Cでさえ分類されないこともあります)。
コンラッドルドルフ

5
データ値にタイプマーカーを持つ(古い)CPUアーキテクチャがあるため、ポインターとして整数を逆参照すると例外が発生します。
サイモンリヒター

8
@JamieHanrahan IA64プロセッサに、値が設定されている場合に例外をスローできるNaT(または「Not a Thing」)と呼ばれるビットがあります
ErikF

4
@KonradRudolph「自動」は「確実に」という意味ではなく、C ++ではありません
-rackandboneman

5

つまり、違いはありません(ただし、intの幅は2または4バイトで、charの幅は1だけです)。

問題は、すべての最新のライブラリがヌルターミネータ技術を使用するか、文字列の長さを保存することです。そして、どちらの場合でも、プログラム/コンピューターは、ヌル文字を読み取るか、サイズが示す数の文字を読み取ったときに、文字列の終わりに到達したことを認識します。

この問題は、nullターミネーターが欠落しているか、プログラムが想定外のメモリーから読み取りを開始するために長さが間違っている場合に発生します。


3
ああ、ショートには違いがあります-実際、ショートは非常にマシン依存のデータ型であることで悪名が高いです:)
rackandboneman

2

違いはありません。マシンコード(アセンブラー)には変数タイプはありませんが、代わりにデータのタイプは命令によって決定されます。

より良い例はでintありfloat、メモリに4バイトがある場合、intそれがaかa float(または他の何か)の情報はありませんが、整数加算と浮動小数点加算には2つの異なる命令があります。命令はデータに対して使用され、それは整数であり、その逆も同様です。

文字列についても同様です。たとえば、アドレスを調べてバイトに達するまでバイトをカウントするコードがある場合、\0文字列の長さを計算する関数と考えることができます。

もちろん、このようなプログラミングは完全に狂気になります。そのため、マシンコードにコンパイルされ、アセンブラーでプログラムをほとんど実行しない高レベル言語があります。


2

科学的な一言で言うと、メタデータです。

メタデータは、特定の場所にあるデータがint、文字列、プログラムコードなどであるかどうかをコンピューターに伝えます。このメタデータは、プログラムコード(Jamie Hanrahanが述べたように)の一部であるか、どこかに明示的に保存できます。

最近のCPUは、多くの場合、プログラムコードに割り当てられたメモリ領域とデータ領域を区別できます(たとえば、NXビットhttps://en.wikipedia.org/wiki/NX_bit)。エキゾチックなハードウェアの中には、文字列と数字を区別できるものもあります、はい。ただし、通常のケースでは、ソフトウェアがこの問題を処理します。暗黙のメタデータ(コード内)または明示的なメタデータ(オブジェクト指向VMは、データ(オブジェクト)の一部としてメタデータ(タイプ/クラス情報)を保存することがよくあります) 。

異なる種類のデータを区別しないことの利点は、一部の操作が非常に単純になることです。I / Oサブシステムは、ディスクから読み取りまたはディスクに書き込むデータが実際にプログラムコード、人間が読めるテキストまたは数値であるかどうかを必ずしも知る必要はありません。機械を通して運ばれるのは、ほんの少しだけです。プログラムコードで派手なタイピングの問題に対処しましょう。


0

そうではありません。あなたはそれを行う!

または、コンパイラ/インタープリター。

指示がコンピュータに0数字として追加するように指示した場合、それが実行されます。に到達した後にデータの印刷を停止するようにコンピューターに指示した場合0、「\0'char 」として実行されます。

言語には、データの処理方法を保証するメカニズムがあります。Cでは変数は種類、等を有していてintfloatそしてchar、コンパイラは、各データ型に右の命令を生成します。しかし、Cを使用すると、変数から別のタイプの別の変数にデータをキャストできます。へのポインターも数値として使用できます。コンピューターにとっては、他のすべてのビットと同じです。


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.