11

私は K&R を読んでいる初心者のプログラマーであり、この本は多くの予備知識を前提としているように感じます。私を混乱させる 1 つの側面は、メモリ内の変数の実際の表現、または存在と言うべきかということです。データ型は変数に対して正確に何を指定しますか? この質問の言い方がよくわかりません...でも、いくつか質問してみると、誰かが首尾一貫した答えをくれるかもしれません。

getchar() を使用する場合、「int」はより多くの値を保持できるのに対し、「char」は 256 個の値しか保持できないため、「char」型よりも「int」型を使用する方がよいと言われました。EOF 値を保持するために変数が必要になる場合があるため、256 文字以上が必要になるか、EOF 値が 256 文字の 1 つと重複します。私の考えでは、これは穴の空いた箱の集まりだと思います。誰かが私により良い表現を与えることができますか? これらの「ボックス」にはインデックス番号がありますか? EOF が 256 の使用可能な値の値と重複する場合、重複する値を予測できますか?

また、これは、char c = 'a' のように変数に手動で値を代入する場合にのみ、データ型「char」を使用しても問題ないということですか?文字?

また、「char」と「int」の実際の重要な違いは何ですか? 「char」タイプの代わりに「int」タイプを使用できる場合、特定の時間に一方を他方よりも優先して使用することに決めたのはなぜですか? 「メモリ」を節約するためですか(「メモリ」が正確にどのように機能するかは実際にはわからないため、引用符を使用します)。

最後に、char 型の 256 個の使用可能な値を正確に取得するにはどうすればよいでしょうか? モジュロ 2^n (n = 8) について読んだことがありますが、なぜそれが機能するのでしょうか (バイナリと関係がありますか?)。「モジュロ 2^n」のモジュロ部分とはどういう意味ですか (モジュロ演算に関連する場合、関係がわかりません...)?

4

10 に答える 10

11

素晴らしい質問です。K&Rは、コンピューターについて知ることがはるかに少なかった時代に書き戻されたため、プログラマーはハードウェアについてより多くのことを知っていました。すべてのプログラマーはこのことをよく知っているはずですが、(当然のことながら)多くの初心者プログラマーはそうではありません。

カーネギーメロン大学では、この知識のギャップを埋めるためにコース全体を開発しました。これは私がTAでした。そのクラスの教科書をお勧めします:「コンピューターシステム:プログラマーの視点」http://amzn.com/013034074X/

あなたの質問への答えはここで実際にカバーできるよりも長いですが、私はあなた自身の研究のためにあなたにいくつかの簡単な指針を与えます。

基本的に、コンピュータは、メモリ(RAM)またはディスクに関係なく、すべての情報を2進数の2進数システム(10進数の10進数ではなく)で格納します。1桁の2桁はビットと呼ばれます。コンピュータは、バイトと呼ばれる8ビットのチャンクでメモリを処理する傾向があります。

Cの文字は1バイトです。intは通常4バイトです(ただし、マシンによって異なる場合があります)。したがって、charは256の可能な値、2^8のみを保持できます。intは2^32の異なる値を保持できます。

詳細については、必ず本を読むか、ウィキペディアのいくつかのページを読んでください。

頑張ってください!

要求に応じて、モジュラー演算に関する情報を更新します。

まず、モジュラー演算について読んでください:http: //en.wikipedia.org/wiki/Modular_arithmetic

基本的に、2の補数システムでは、nビット数は実際には2^nを法とする整数の同値類を表します。

それがそれを少なくするのではなくより複雑にするように思われる場合、知っておくべき重要なことは単純です:

  • 符号なしnビット数は、0から2^n-1までの値を保持します。値は「ラップアラウンド」するため、たとえば、2つの数値を加算して2 ^ nを取得すると、実際にはゼロになります。(これは「オーバーフロー」と呼ばれます。)
  • 符号付きnビット数は、-2 ^(n-1)から2 ^(n-1)-1までの値を保持します。数値は引き続きラップアラウンドしますが、最大の数値は最も負の数値にラップアラウンドし、そこからゼロに向かってカウントアップを開始します。

したがって、符号なしバイト(8ビット数)は0〜255になります。255+1は0にラップアラウンドします。255+2は1になります。符号付きバイトは-128〜127にすることができます。127+1は最終的に-128になります。(!)127+2は-127などになります。

于 2010-01-09T17:34:08.513 に答える
5

私を混乱させる1つの側面は、メモリ内の変数の実際の表現、つまり存在と言えばです。データ型は変数に正確に何を指定しますか?

intマシンレベルでは、との違いはchar、プログラミング言語によって割り当てられたメモリのサイズまたはバイト数だけです。C、IIRCでは、acharは1バイトで、anintは4バイトです。マシン自体の内部でこれらを「見る」とすると、それぞれのビットのシーケンスが表示されます。intそれらを言語がどのように解釈するかによって、またはそれらを扱うことができるcharかどうかに依存します(これが、2つのタイプ間で前後に変換できる理由でもあります)。

getchar()を使用する場合、「int」はより多くの値を保持できるのに対し、「char」は256の値しか保持できないため、「char」型よりも「int」型を使用する方がよいと言われました。

これは、8ビットの組み合わせが2 ^ 8、つまり256あるのに対し(ビットには2つの可能な値があるため)、32ビットの組み合わせは2^32であるためです。EOF定数(Cで定義)は負の値であり、0から255の範囲内にありません。この負の値をcharに割り当てようとすると(これにより、4バイトが1に圧縮されます)、上位ビットがが失われ、EOFと同じではない有効なchar値になります。これが、charにキャストする前にintに格納してチェックする必要がある理由です。

また、これは、データ型「char」は、0char c ='a'などの変数に値を手動で割り当てるだけで、256個のASCIIしか使用できないことが確実にわかっている場合にのみ使用できることを意味しますか?文字?

はい、特にその場合は文字リテラルを割り当てているためです。

また、「char」と「int」の実際の重要な違いは何ですか?「char」型の代わりに「int」型を使用できるのに、なぜ特定の時間に一方を他方の上に使用することにしたのでしょうか。

最も重要なことは、変数を数字として扱うか文字として扱うかに応じて、言語レベルで選択するか、言語レベルで選択することです(切り替えるには、他のタイプにキャストする必要があります)intcharより少ないスペースを占める整数値が必要な場合は、short int(2バイトだと思います)を使用できます。または、メモリ使用量に本当に関心がある場合は、を使用できますがchar、ほとんどの場合、これは必要ありません。

編集:Cのさまざまなデータ型とそれらに適用できる修飾子を説明するリンクは次のとおりです。サイズと値の範囲については、最後の表を参照してください。

于 2010-01-09T17:31:49.360 に答える
4

基本的に、システム メモリは 1 つの巨大な一連のビットであり、それぞれが「オン」または「オフ」のいずれかになります。残りは慣習と解釈です。

まず、個々のビットに直接アクセスする方法はありません。代わりに、それらはバイトにグループ化され、通常は 8 つのグループ (これが当てはまらない特殊なシステムがいくつかありますが、今は無視してかまいません) であり、各バイトはメモリ アドレスを取得します。したがって、メモリの最初のバイトはアドレス 0、2 番目のバイトはアドレス 1 などになります。

8 ビットのバイトには 2^8 の異なる値があり、0 ~ 255 (符号なしバイト) の数値、-128 ~ +127 (符号付きバイト) の数値、または ASCII 文字として解釈できます。C 標準の型の変数のcharサイズは 1 バイトです。

しかし、バイトは多くのことに対して小さすぎるため、より大きな (つまり、複数のバイトで構成される) 他の型が定義されており、CPU は特別なハードウェア構造を通じてこれらの異なる型をサポートしています。int4 バイトは 32 ビットであり、最近まで主流の CPU が「ワード サイズ」としてサポートしていたものであるため、最近ではAnは通常 4 バイトです (ただし、C 標準では指定されておらず、異なるシステムでは int が小さくても大きくてもかまいません)。

したがって、型の変数intは 4 バイトの大きさです。つまり、メモリ アドレスがたとえば 1000 の場合、実際にはアドレス 1000、1001、1002、および 1003 のバイトをカバーします。C では、これらの個々のバイトを同時にアドレス指定することも可能です。重ねることができます。

補足として、ほとんどのシステムでは、より大きな型を「ワード アライン」する必要があります。つまり、アドレスはワード サイズの倍数にする必要があります。これにより、ハードウェアが処理しやすくなります。そのため、int 変数をアドレス 999 またはアドレス 17 で開始することはできません (ただし、1000 および 16 は問題ありません)。

于 2010-01-09T17:40:55.433 に答える
3

私はあなたの質問に完全に答えるつもりはありませんが、私が自分でプログラミングを始めたとき、変数を理解するのと同じ問題を抱えていたので、あなたが変数を理解するのを手伝いたいと思います.

今のところ、メモリ内の変数の電子表現を気にしないでください。メモリは、1 バイト セルの連続したブロックであり、それぞれがビット パターン (0 と 1 で構成される) を格納していると考えてください。

メモリを見るだけでは、その中のビットが何を表しているかを判断することはできません! それらは、0 と 1 の任意のシーケンスです。これらのビットパターンをどのように解釈するかを指定するのはあなたです! 次の例を見てください。

int a, b, c;
...
c = a + b;

次のように書くこともできます。

float a, b, c;
...
c = a + b;

どちらの場合も、変数 a、b、c はメモリのどこかに保存されます (そして、それらの型はわかりません)。ここで、コンパイラがコードをコンパイルするとき (つまり、プログラムを機械語命令に変換するとき)、最初のケースでは "+" を integer_add に、2 番目のケースでは float_add に変換するため、CPU はビット パターンを解釈します。あなたが望むものを正しく実行します。

変数の型はメガネのようなもので、CPU がビット パターンをさまざまな視点から見ることができます。

于 2010-01-09T18:07:02.383 に答える
2

G'day、

さらに深く掘り下げるには、チャールズ・ペッツォルドの優れた本「コード」を強くお勧めします。

それはあなたが尋ねるもの以上のものをカバーします、そしてそれはすべてカバーの下で実際に起こっていることのより良い理解につながります。

HTH

于 2010-01-09T17:28:19.493 に答える
1

実際、データ型は、プログラミング言語が特定のアドレスの数バイトをある種の数値型として扱うことを可能にする抽象化です。データ型を、メモリの一部をintまたはfloatとして表示できるレンズと見なします。実際には、それはすべてコンピュータにとってほんの少しのことです。

于 2010-01-09T17:30:52.623 に答える
1
  • C ではEOF、「小さな負の数」です。
  • C では、char型は符号なしの場合があります。つまり、負の値を表すことはできません。
  • 符号なしの型に負の値を代入しようとすると、符号なしの値に変換されます。MAXが符号なし型が保持できる最大値である場合、-nそのような型への代入はそれに代入することと同じMAX - (n % MAX) + 1です。したがって、予測に関する特定の質問に答えるには、「はい、できます」。たとえば、が符号なしで、包括的にchar0を保持できるとしましょう。255次に-1、char への代入はそれに代入255 - 1 + 1 = 255することと同じです。

上記を考えると、 に格納できるようにするにEOFc、型にcすることはできませんchar。したがって、int「小さな負の値」を格納できるため、 を使用します。特に C では、とintの範囲の値を格納することが保証されています。それが を返す理由です。-32767+32767getchar()int

また、これは、char c = 'a' のように変数に手動で値を代入する場合にのみ、データ型「char」を使用しても問題ないということですか?文字?

値を直接代入している場合、C 標準では、式 like'a'が a に収まることが保証されていcharます。C では、は char ではなく'a'型であることに注意してください。intchar c = 'a''a'char

変数が保持する必要がある型に関する質問については、答えは次のとおりです。意味のある型を使用してください。たとえば、文字列の長さを数えたり調べたりしている場合、数値はゼロ以上である必要があります。そのような場合は、unsigned 型を使用する必要があります。 size_tはそういうタイプです。

データの種類を把握するのが難しい場合があり、「プロ」でさえ間違いを犯す可能性があることに注意してください。 gzipたとえば、圧縮されていないデータのサイズをファイルの最後の 4 バイトに格納します。これは、サイズが 4 GB を超える巨大なファイルの場合に壊れます。これは、最近ではかなり一般的です。

用語には注意が必要です。C では、a はに対応するchar c = 'a'整数値を割り当てますが、ASCII である必要はありません。それは、たまたま使用するエンコーディングに依存します。'a'c

「モジュロ」部分と type の 256 個の値についてchar:nデータ型にバイナリ ビットがある場合、各ビットは 0 と 1 の 2 つの値をエンコードできます。したがって、2*2*2...*2(n倍の) 利用可能な値、つまり 2 nがあります。符号なしの型の場合、オーバーフローは明確に定義されており、数値を (可能な最大値 + 1) で割り、余りを取ったようなものです。たとえば、unsigned char値を格納できるとします0..255(合計 256 個の値)。次に、に代入257すると、unsigned char基本的に256で除算され、剰余(1)が取り、その値が変数に代入されます。ただし、この関係は unsigned 型にのみ当てはまります。詳細については、別の質問に対する私の回答を参照してください。

最後に、char配列を使用して C でファイルからデータを読み取ることができます。最終的には にヒットする可能性があります。Cには、変数で明示的にデータを読み取らずEOFに検出する他の方法が用意されているためです。EOF配列とポインターについて読んでください ( fgets()1 つの例に興味がある場合は参照してください)。

于 2010-01-09T17:38:13.263 に答える
0

言語で必要なすべての文字は、ASCII および拡張 ASCII で表されます。したがって、拡張 ASCII を超える文字はありません。

char を使用すると、文字を直接格納するため、ガベージ値を取得する可能性がありますが、int を使用すると、文字の ASCII 値を格納するため、その可能性は低くなります。

于 2014-01-14T19:55:14.923 に答える
0

「stdio.h」によると、getchars() の戻り値は int で、EOF は -1 として定義されています。実際のエンコーディングによっては、0..255 の間のすべての値が発生する可能性があるため、unsigned char では -1 を表すのに十分ではなく、int が使用されます。これは詳細な情報を含む素晴らしい表ですhttp://en.wikipedia.org/wiki/ISO/IEC_8859

于 2010-01-09T17:37:27.810 に答える
0

K&R の優れた点は、その簡潔さと読みやすさです。ライターは常に目標のために譲歩しなければなりません。2000 ページのリファレンス マニュアルではなく、基本的なリファレンスとして機能し、言語全般を学習するための優れた方法です。詳細については、優れた C リファレンス ブックとして Harbinson と Steele の「C: A Reference Manual」をお勧めします。もちろん、C 標準もお勧めします。

このようなことを喜んでグーグルする必要があります。変数はメモリ内の特定の場所で表され、指定されたスコープ内の一部であるプログラムに認識されます。char は通常、8 ビットのメモリに格納されます (一部のまれなプラットフォームでは、これは必ずしも正しくない場合があります)。2^8 は、変数の 256 の異なる可能性を表します。異なる CPU/コンパイラ/etc は、さまざまなサイズの基本型 int、long を表します。C標準では、これらの最小サイズを指定している可能性がありますが、最大サイズは指定していないと思います。double の場合、少なくとも 64 ビットを指定すると思いますが、これはインテルが浮動小数点ユニットで 80 ビットを使用することを妨げません。いずれにしても、32 ビット Intel プラットフォームの一般的なメモリ サイズは、unsigned/signed int および float の場合は 32 ビット (4 バイト)、double の場合は 64 ビット (8 バイト)、char (signed/unsigned) の場合は 8 ビットです。トピックに本当に興味がある場合は、メモリの配置も調べる必要があります。「&」演算子を使用して変数のアドレスを取得し、そのアドレスを覗いて、デバッガーの正確なレイアウトを確認することもできます。Intel プラットフォームでは、メモリ内の値を見ると少し混乱する可能性があるため、リトル エンディアン/ビッグ エンディアンも調べてください。スタック オーバーフローにも、これに関するいくつかの優れた要約があると確信しています。

于 2010-01-09T17:40:11.207 に答える