3

実際、ループを使用してコードをより効率的にする方法について研究しました。これにより、特定のコードブロックを何度も入力せずに繰り返す必要があり、学んだことを使用しようとした後、何かをプログラムするにはほど遠いので、次の章に進み、制御ステートメントを使用してプログラムに決定を指示する方法を学ぶ時が来たと感じています。

しかし、問題は、私がそれに進む前に、以前のものについて専門家の助けが必要ないくつかの質問がまだあるということです. 実際にはデータ型についてです。


A. キャラクタータイプ

  1. 本 C 入門プラス第 5 版から以下を抜粋します。

やや奇妙なことに、C は文字定数をintではなく 型として扱いcharます。たとえば、32 ビットintと 8ビットの ASCII システムでchar は、コードは次のようになります。

char grade = 'B';

'B'は 32 ビット単位で格納された 66 を数値として表し、 grade 8 ビット単位で格納された 66 の ub ab で終わります。'FATE'文字定数のこの特性により、32 ビット単位に格納された 4 つの別個の 8 ビット ASCII コードを使用して、などの文字定数を定義することができます。ただし、このような文字定数を変数に割り当てようとするとchar、最後の 8 ビットしか使用されないため、変数は値を取得します'E'

  1. したがって、これを読んだ後に私が次に行ったことは、もちろん、それが言及していることに従いFATEましたchar grade.アウト、私が得るものは.printf()'E''F'

  2. これは本に間違いがあるということですか?または私が誤解したことがありますか?

  3. 上記の文から、C は文字定数を type として扱うという行がありintます。試しに、型に255, (ex 356)より大きい数値を割り当てcharます。

  4. 356は 32 ビットの範囲内にあるため(Windows 7 を実行しています)、指定子を使用するとint出力されると予想されます。356%d

  5. しかし、 を出力する代わりに、最後の 8 ビット値である が356得られます。100

  6. なぜこれが起こるのですか?私は思ったchar == int == 32-bits?(char がバイトにすぎない前に言及していますが)。


B. Int 型と Floating 型

  1. 型の変数に格納された数値がshort可変引数関数または暗黙のプロトタイプ関数に渡されると、自動的にint型に昇格されることを理解しています。

  2. これは浮動小数点型にも起こります。型を持つ浮動小数点数floatが渡されると、double型に変換されます。そのため、型の指定子はなく、代わりにforとforfloatしかありません。%fdouble%Lflong double

  3. しかし、short昇格されてもタイプではないのに、なぜタイプの指定子があるのfloatでしょうか? float修飾子などを使用して型の指定子を指定しないのはなぜ%hfですか? この背後に論理的または技術的な何かがありますか?

4

4 に答える 4

2

1 つの質問に多くの質問があります。いくつかの質問への回答を次に示します。

文字定数のこの特性により、'FATE' などの文字定数を、32 ビット単位に格納された 4 つの別個の 8 ビット ASCII コードで定義することができます。ただし、そのような文字定数を char 変数に代入しようとすると、最後の 8 ビットのみが使用されるため、変数は値「E」を取得します。

これは実際には実装定義の動作です。はい、そうです、本に間違いがあります。C に関する多くの本は、世界で唯一の C コンパイラーが、著者が例をテストするときに使用したものであるという前提で書かれています。

著者が使用するコンパイラは、'FATE' の文字を整数のバイトとして扱い、'F' が最上位バイトで、'E' が最下位バイトです。コンパイラは、リテラル内の文字を整数のバイトとして扱います。「F」は最下位バイトで、「E」は最上位バイトです。たとえば、最初の方法は MSVC が値を処理する方法ですが、MinGW (Windows を対象とする GCC コンパイラ) はリテラルを 2 番目の方法で処理します。

printf()that expectsへの書式指定子がない限りfloat、expect の指定子についてdouble- これは、printf()書式設定のために に渡される値が可変引数リスト ( ...inprintf()のプロトタイプ) の一部であるためです。これらの引数に関する型情報がないため、前述のように、コンパイラは常にそれらを昇格する必要があります(C99 6.5.2.2/6「関数呼び出し」から):

呼び出された関数を示す式の型がプロトタイプを含まない場合、各引数に対して整数昇格が実行され、float 型の引数は double に昇格されます。これらは、デフォルト引数プロモーションと呼ばれます。

そしてC99 6.5.2.2/7「関数呼び出し」

関数プロトタイプ宣言子の省略記号表記により、最後に宣言されたパラメーターの後で引数の型変換が停止します。デフォルトの引数昇格は、末尾の引数に対して実行されます。

floatつまり、 toを渡すことは事実上不可能printf()です - それは常に a に昇格されますdouble。そのため、浮動小数点値の書式指定子はdouble.

また、に適用される自動昇格のため、 a をフォーマットするための指定子が厳密に必要shortかどうかは正直わかりません(ただし、ストリームに書き込まれた文字数を取得する場合は、指定子と一緒に使用する必要があります)に配置)。指定子、歴史的理由、または私が考えていない何かをサポートするためにそこにある必要があるため、C にある可能性があります。hshortnshortn

于 2011-05-15T18:46:17.123 に答える
1

まず、achar定義上、正確に 1 バイト幅です。次に、標準では、サイズは次のようにする必要があります。

sizeof(char) <= sizeof(short) <= sizeof(int) <= sizeof(long)

正確なサイズはcharシステムとコンパイラによって異なりますが (を除く)、32 ビット Windows では GCC と VC のサイズは (AFAIK):

sizeof(short) == 2 (byte)
sizeof(int) == sizeof(long) == 4 (byte)

この場合の「F」と「E」の観察は、典型的なエンディアンの問題です (リトル エンディアンとビッグ エンディアン、「単語」がメモリに格納される方法)。

あなたの価値はどうなりますか?8 ビット幅の変数があります。'FATE'より大きな値 (または) を割り当てます356が、コンパイラは 8 ビットしか格納できないことを認識しているため、他のすべてのビットを切り捨てます。

于 2011-05-15T14:18:34.430 に答える
0

A へ: 3.) これは、ビッグ エンディアンとリトル エンディアンの CPU アーキテクチャのバイト順が異なるためです。リトル エンディアン (つまり x86) では最初のバイトを取得し、ビッグ エンディアン CPU (つまり PPC) では最後のバイトを取得します。int から char への変換が行われると、実際には常に最下位の 8 ビットが取得されますが、int 内の文字は逆の順序で格納されます。

7.) char は 8 ビットしか保持できないため、int を char 変数に割り当てた瞬間に他のすべてが切り捨てられ、後で char 変数から復元することはできません。

B へ: 3.) int 変数の上位半分に関係なく、下位 16 ビットのみを出力したい場合があります。特定の最適化のために、複数の整数値を 1 つの変数にパックすることは珍しくありません。これは整数型ではうまく機能しますが、ビット単位の演算を直接サポートしていない浮動小数点型ではあまり意味がありません。これが、printf に float の個別の型指定子がない理由である可能性があります。

于 2011-05-15T14:17:39.953 に答える
0

char長さは 1 バイトです。バイトのビット長は、8、16、32 ビット長です。汎用コンピュータでは、通常、文字のビット長は 8 ビット長です。したがって、文字が表現できる最大数は、文字のビット長によって異なります。文字チェックlimits.hヘッダーファイルのビット長をチェックするにはCHAR_BIT、このファイルのように定義されています。

char x = 'FATE'おそらく、マシン/コンパイラが 'FATE' を解釈するバイト順序に依存します。したがって、これはシステム/コンパイラに依存します。誰かこれを確認/修正してください。

システムに 8 ビットのバイトがある場合、データには常に 1 バイトのストレージが割り当てられるc = 360ため、360 のバイナリ表現の下位 8 ビットのみが変数に格納されます。char変数%dに値を割り当てたときに上位ビットが失われ、下位 8 ビットだけが残っているため、100 が出力されます。

于 2011-05-15T14:24:38.850 に答える