知識の源 [C Prime Plus 第 6 版] [インターネット]
目次
- 1. はじめてのC言語入門
- C言語の特徴とキーワード
- 翻訳者
- C 言語プログラミングの基本戦略:
- 2. 簡単な C プログラム例の概要
- 3. データと C (基礎知識)
- 変数と定数
- データの種類
- 整数と浮動小数点数
- 浮動小数点数
- int型
- 8進数と16進数を表示
- 他の整数型
- 複数の整数型を使用する理由
- 長い定数と長い長い定数
- 使用文字:char型
- 文字定数と初期化
- 非印刷文字
- Bool型Boolean型
- Float、int和double
- sizeof() 関数
- 4. 文字列とフォーマットされた入出力
- 弦
- char型配列とnull文字
- 配列
- 文字列と文字
- strlen() 関数
- 定数と C プリプロセッサ
- #definepredirective
- const修飾子
- 明示的な定数
- printf() と scanf() および I/O 関数
- フィールド幅プログラム
- 浮動小数点バイト幅出力
- 変換記述の意味
- 変換の不一致
- 5. 演算子、式、およびステートメント
- 6. C制御文:ループ
- 7. C 制御ステートメント: 分岐とジャンプ
- 8. 文字の入出力と入力確認
- 9. 機能
- 10. 配列とポインタ
- 11. 文字列と文字列関数
- 12. ストレージ カテゴリ、リンク、メモリ管理
- 13. ファイル入出力
- 14. 構造体とその他のデータ型
- 15. ビット演算
- 16. CプリプロセッサとCライブラリ
- 17. 高度なデータ表現
- 18. リファレンススクリーニング
序文
今回は「Cプライムプラス」といくつかのオンライン講座を通じて学習し、統合された知識体系をこの記事にまとめました。
内容は長いので、まとめることをお勧めします。コメント欄での議論を歓迎します〜
1. はじめてのC言語入門
C言語の特徴とキーワード
- 最下層に近い: 高速に動作し、最下層の開発で広く使用されており、オペレーティング環境を必要としません。
- プログラマのニーズに応えて、ハードウェアにアクセスしたり、メモリ内のビットを操作したり、豊富な演算子を備えていますが、奇妙な間違いを犯しやすいです。
- 通常はアセンブリ言語でのみ利用できる微調整制御機能を使用すると、特定の条件に応じてプログラムを微調整して、最大の実行速度やメモリの最も効率的な使用を実現できます。
- 移植性: 同じ標準プログラムを、組み込みプロセッサ (シングルチップ コンピュータまたは MCU) やスーパーコンピュータなどの異なるプラットフォーム上で実行できます。
- C 言語はポインターの使用に重点を置いており、それに伴うエラーの検出が難しいことが多いという欠点もあります。
- 国際標準: ANSIC、米国標準局によって開発されました。
翻訳者
Visual Studio Community 2019 (VS2019 Community Edition) を使用します。
vs2019 インストールリンク: https://pan.baidu.com/s/12yzsJuL8t67caNthSbQaAw抽出コード: t9em
インストールするときは、必ずパスを切り替え、C++ を使用したデスクトップ開発をチェックしてください。
インストール後、コンピュータを再起動します。
C 言語プログラミングの基本戦略:
C 言語プログラミングの基本戦略は、プログラムを使用してソース コード ファイルを実行可能ファイル(直接実行できる機械語コードが含まれる) に変換することです。
一般的な C 実装では、このプロセスはコンパイルとリンクの2 つのステップで完了します。
コンパイラはソース コードを中間コードに変換し、リンカは中間コードを他のコードとマージして実行可能ファイルを生成します。
C では、この分割統治アプローチを使用してプログラムのモジュール化を促進しており、個々のモジュールを独立してコンパイルでき、コンパイルされたモジュールは後でリンカーを使用してマージできます。こうすることで、1 つのモジュールのみを変更した場合、他のモジュールを再コンパイルする必要がなくなります。
さらに、リンカはプログラマが作成したプログラムをプリコンパイルされたライブラリ コードとマージします。
したがって、C プログラムの実行プロセスはコンパイル + リンク + コードの実行となり、ファイルの拡張子は.c --> .obj --> .exeとなります。
このプロセスでは、オブジェクト ファイルと実行可能ファイルの両方が機械語命令で構成されます。
ただし、オブジェクト ファイルには、プログラマが作成したコードをコンパイラが変換する機械語コードのみが含まれており、実行可能ファイルには、プログラマが作成したプログラムで使用されるライブラリ関数のマシン語コードとスタートアップ コードも含まれています。
- 知識と常識を充電する:
- ソース コード: プログラマによって作成された C 言語コード ファイルで、コンパイラの作成ページに反映され、接尾辞 .c が付きます。
- オブジェクトファイル: ソースコードをコンパイルした後に生成されるバイナリコードであり、実行することはできません、拡張子は.obj または .o (linux) です。
- 実行可能ファイル: リンカを介してオブジェクト コード、ライブラリ関数コード、およびシステム標準起動コードを結合することにより、オペレーティング システム上で独立して実行できる完全なプログラム ファイル (拡張子 .exe が付いています)
- ライブラリ関数: C 言語の関数ライブラリに格納されている関数を指します。ライブラリとは、 C 言語の創始者によって書かれた一般的に使用される関数の集合です。一般的な用語です。ライブラリ関数の呼び出しは主に#include<stido.h> などのヘッダー ファイル
- マシンコード: CPU が直接実行できる 2 進数のセット。マシン語とも呼ばれます。機械語のデジタル命令セットはアセンブリ言語を構成し、アセンブリ言語を抽象化した高級言語になりますが、代表的な高級言語としてはC言語が挙げられますので、興味のある方は関連知識を検索してみてください。
2. 簡単な C プログラム例の概要
この章では、簡単なプログラム例から始まり、プログラムの機能を説明し、C 言語の基本的な機能をいくつか紹介します。
#include <stdio.h>
int main(void)
/*一个简单的C程序*/
{
int num; /*定义一个名为num的变量*/
num = 1; /*为num赋一个值*/
printf("I am a Programmer"); /*使用printf()函数进行输出*/
printf("\n"); /*使用\n换行*/
printf("computer.\n");
printf("My favorite number is &d because it is first.\n", num);
return 0;
}
このプロセス中、C 言語プログラムは次のように実行されます。
以下では、このプログラムを 1 行ずつ説明します。
#include<stdio.h>
これはプログラムの 1 行目です。#include<stdio.h> の機能は、stdio.h ファイルのすべての内容をこの行の場所に入力することと同じです。実際、これは「コピーアンドペースト」操作です。インクルード ファイルは、多くのプログラムに共通する情報を共有する便利な方法を提供します。コードの #include 行は、C プリプロセッサ ディレクティブです。C コンパイラは、コンパイル前にソース コードの準備作業、つまり前処理を行います。すべての C コンパイラ パッケージは stdio.h ファイルを提供します。このファイルには、コンパイラによって使用される入力関数と出力関数 (出力関数 Printf() など) が含まれています。このファイル名の意味は、標準入出力ヘッダー ファイルです。通常、C プログラムの先頭にある情報の集合はヘッダーと呼ばれます。
それなら、入出力関数を組み込んでみませんか?
理由の 1 つは、すべてのプログラムがI/O (入力/出力) パッケージを使用するわけではないことです。身軽に旅行することは、C 言語の哲学を反映しています。C が人気の組み込みプログラミング言語になっているのは、このリソースの経済的使用の原則です (たとえば、車の自動燃料システムや Blu-ray プレーヤー チップを制御するコードの作成)。
メイン機能
main() 関数は C 言語プログラムの入り口であり、プログラムは main() 関数から実行を開始する必要があります (現時点では例外を考慮する必要はありません)。main 関数に加えて、他の関数に任意の名前を付けることもできます。main 関数は開始関数である必要があります。括弧 () は main を関数として識別するためのものです。
コメント
プログラム中、/**/で囲まれた部分がプログラムのコメントです。コメントを書くことで、自分自身を含む他の人が自分の書いたプログラムを理解しやすくなります。
C 言語のコメントの利点の 1 つは、説明する内容と同じ行であっても、どこにでも配置できることです。
長いコメントは 1 行または複数行に含めることができます。/* と */ の間にあるものはすべてコンパイラによって無視されます。
/*这是一条C注释。*/
/*这也是一条注释,
被分成两行。*/
/*
也可以这样写注释。
*/
/*这条注释无效,因为缺少了结束标记。
中括弧、関数本体、およびブロック
一般に、すべての C 関数は中括弧{ }を使用して関数本体の開始と終了をマークします。これはカメのお尻のルールであり、これを行うことができる中括弧があります。
声明
int num = 1;
このコード行は宣言と呼ばれます。宣言は C 言語の最も重要な機能の 1 つです。この例では、ステートメントは 2 つのことを実現します。
まず、関数内に num という名前の変数があることが示されています。2 番目に、int は num 変数が整数であり、int がデータ型であることを示します (整数は小数点や小数部のない数値です)。コンパイラはこの情報を使用して、メモリ内の記憶領域を num 変数に割り当てます。セミコロンは、C のほとんどのステートメントと宣言の一部です。int はC 言語のキーワードであり、基本的な C 言語データ型を表します。キーワードは言語によって定義された単語であり、他の目的には使用できません。この例の num は、変数、関数、またはその他のエンティティの名前であるidentifierです。したがって、宣言は特定の識別子をコンピュータ メモリ内の特定の場所に関連付け、またその場所に格納されている情報またはデータの種類も識別します。
C 言語では、すべての変数を使用する前に宣言する必要があります。これは、プログラムで使用されるすべての変数名とその型をリストする必要があることを意味します。
return ステートメント
return ステートメントは最後のステートメントです。main() の int は、main() 関数が整数を返す必要があることを示します。
ステートメントは return キーワードで始まり、その後に返される値が続き、セミコロンで終わります。main()関数のreturn文を省略した場合、プログラムは一番外側の右中括弧(})に到達した時点で0を返します。したがって、main() 関数の最後の return ステートメントは省略できます。ただし、値を返す関数では return を省略しないでください。
このうち、戻り値 0 はプログラムが正常に終了したことを意味し、戻り値が0 以外の場合はプログラムが異常終了したことを意味します。この情報はコンソール、つまりオペレーティング システムに返され、プログラム自体には影響を与えません。void main() プログラムでは、値を返す必要はありません。さらに、return の後には式が続きます。式には、即値、変数、または計算式や変数を指定できます。
3. データと C (基礎知識)
変数と定数
C言語プログラムの実行中、値が変化しない量を定数と呼びます。これには、直接定数と記号定数(直接定数ではありません)が含まれます。
- 直接定数
直接出力できる定数には、整数定数(数個の整数)、実数定数(数個の小数)、文字定数(数個の文字)が含まれますが、これらに限定されません。
- 記号定数
識別子を使用して定義された定数: シンボリック定数は使用前に定義する必要があり、通常はヘッダー ファイルの下に配置されます。フォーマットは
#define 标识符 常量
たとえば、pi 3.1415926 を定数 p として定義します。
#include<stdio.h>
#define p 3.1415926
データの種類
C言語のデータ型は、基本データ型、構築データ型、ポインタ型、null型の4つに分類できます。
その中で、実際に最も頻繁に使用されるのは、整数型、実数型、および文字型です。
データの種類 | タイプ | バイト | 応用 | 例 |
文字 | 文字の種類 | 1 | 単一文字を保存する | 文字名 = 'S'; |
整数 | 形成外科 | 2 | 整数を保存する | 整数年齢 = 18; |
浮く | 単精度浮動小数点 | 4 | マウスの保管 | 変動価格 = 99.9; |
ダブル | 倍精度浮動小数点 | 8 | より多くの桁数の小数を格納する | 二重円周率 = 3.1415926; |
ビット、バイト、ワード:
ビット、バイト、ワードは、コンピュータのデータまたはストレージの単位を表す用語です。これは主にストレージユニットを指します。
ビット (bi) は、 0 または 1 を格納できる最小の記憶単位です (つまり、ビットは「オン」または「オフ」を設定するために使用されます)。限られた情報を保存できるのは 1 ビットだけですが、コンピューター内のビット数は膨大です。ビットは、コンピューター メモリの基本的な構成要素です。
バイト (byte) は、一般的に使用されるコンピュータの記憶単位です。ほとんどすべてのマシンでは、1 バイトは 8 ビットです。これは、少なくともストレージ単位を測定する場合のバイトの標準定義です (ただし、C 言語ではこれとは異なる定義があります。この章のセクション 3.4.3 を参照)。1 ビットは 0 または 1 を表すことができるため、8 ビット バイトでは 256 (2 の 8 乗) 通りの 0 と 1 の組み合わせが可能です。バイナリ エンコード (数値は 0 と 1 だけで表現できる) により、0 から 255 までの整数または文字のグループを表現できます。
単語は、コンピュータを設計するときに与えられる自然な記憶単位です。8 ビット マイクロコンピュータ (初代 Mac など) の場合、ワード長はわずか 8 ビットです。それ以来、パーソナル コンピューターのワード長は 16 ビット、32 ビット、そして現在は 64 ビットと増加してきました。コンピュータのワード サイズが大きいほど、データ転送が速くなり、より多くのメモリ アクセスが許可されます。
整数データは次のように細分化できます。
データの種類 | タイプ | バイト | 範囲 |
整数 | 整数 | 2 または 4 | それは状況によります |
短い整数 | 短整数型(intは省略可) | 2 | (-32768~32767) |
長い整数 | 長整数型(intは省略可) | 4 | (-2147483648~2147483647) |
符号なし整数 | 符号なし型 | 2 または 4 | それは状況によります |
ため息なしの short int | 符号なしショート | 2 | (0~65536) |
符号なし長整数 | 符号なし長整数 | 4 | (0~4294967295) |
値の範囲の計算ルール。n はバイト数を表します。
- int short long: 2の((2*n)-1)乗~2の((2*n)-1)-1乗
- unsignde int short long: 0 ~ 2 の (2*n)-1 乗
なお、int のバイト数はコンパイラの規定により 2 バイトまたは 4 バイトになりますが、一般的に VIsual C++ では 4 バイトを占有します。Int short double もコンパイル環境によって異なる値がとられますが、short と lont の最小値は表に書いたとおりです。
ただし、暗記する必要はなく、sizeof()関数を呼び出してバイトを計算し、ルールに従って値の範囲を解決できます。
PS:ここでの\t は、プログラム出力を見やすくするためのタブ文字を表します。
#include <stdio.h>
int main()
{
printf("char:\t\t%d\t\n", sizeof(char));
printf("short:\t\t%d\n", sizeof(short));
printf("int:\t\t%d\n", sizeof(int));
printf("long:\t\t%d\n", sizeof(long));
printf("long long:\t%d\n", sizeof(long long));
printf("float:\t\t%d\n", sizeof(float));
printf("double:\t\t%d\n", sizeof(double));
printf("longdoule:\t%d\n", sizeof(long double));
return 0;
}
\t是制表符 便于输出结果的排版
整数と浮動小数点数
整数とは、小数部分のない数値です。たとえば、2、-23、および 12312312 はすべて整数です。また、3.1415、6.0000 など、小数点のあるものは整数ではありません。
コンピュータでは、整数は 2 進数として格納されます。たとえば、整数 7 は 2 進数で 111 です。したがって、この数値を 8 ビット バイトに格納するには、最初の 5 ビットを 0 に設定し、最後の 3 ビットを 0 に設定する必要があります。 1.
浮動小数点数
浮動小数点数は数学の実数に似ています。たとえば、2.75、3.16E7、6.00、2e-8 はすべて浮動小数点数です。PS: 値の後に小数点を追加すると、値は浮動小数点値になります。したがって、7 は整数、7.00 は浮動小数点数です。浮動小数点数を記述するには、e 表記など、さまざまな形式があります。
ここで、浮動小数点数と整数の記憶方式が異なることを強調します。コンピュータは浮動小数点数を小数部分と指数部分に分割し、これら 2 つの部分を別々に保存します。したがって、7.00 と 7 は数値的には同じですが、格納方法が異なります。コンピューターの内部では、ストレージに 10 の累乗ではなく、バイナリと 2 の累乗が使用されます。
2 つの実際の違いは次のとおりです。
- 整数には小数部がありませんが、浮動小数点数には小数部があります。
- 浮動小数点数は、整数よりも広い範囲を表すことができます。
- 一部の算術演算 (2 つの非常に大きな数値の減算など) では、浮動小数点数の精度がさらに失われます。
- どの区間(たとえば、1.0 から 2.0 の間)にも無限に多くの実数が存在するため、コンピュータの浮動小数点数は区間内のすべての値を表すことはできません。浮動小数点数は通常、実際の値の近似値にすぎません。たとえば、7.0 は浮動小数点値 6.99999 として保存される場合があります。
- 以前は、浮動小数点演算は整数演算よりも低速でした。ただし、現在では多くの CPU に浮動小数点プロセッサが搭載されており、速度の差は縮まっています。
int型
int 型は符号付き整数型です。つまり、int 型の値は整数である必要があり、正の整数、負の整数、またはゼロを指定できます。その値の範囲はコンピュータ システムによって異なります。
一般に、int を格納するには 1 つのマシンワードが必要です。したがって、初期の 16 ビット IBM PC 互換機は、int 値の格納に 16 ビットを使用し、その値の範囲 (つまり、int 値の値の範囲) は -32768 ~32767 でした。現在のパソコンは 32 ビットが一般的ですので、1t の値を格納するには 32 ビットが使用されます。現在、パーソナル コンピュータ業界は、より大きな整数を自然に格納できる 64 ビット プロセッサに向けて徐々に発展しています。IS0 C では、int の最小値の範囲は -32768 ~ 32767 であると規定されています。
一般に、従来のコンピュータ システムは、特殊ビットの値を使用して符号付き整数の符号を表します。
int変数を宣言する
最も簡単な方法は、int 変数名、または int の後にカンマで区切ってリストされた複数の変数名を使用することです。栗をあげます:
int watermelon;
int tsama, watermelon, goats;
//切记不要忘记分号;
変数を作成したら値を代入する必要がありますが、大きく分けて3つの方法があります。栗をあげます:
int watermelon = 1;//在声明的基础上就赋值
int watermelons;
watermelons = 1219;//声明后再赋值
int watermelonss;
scanf("%d",&watermelonss);//通过函数赋值
変数の宣言はメモリ空間を開くことに相当し、代入は宣言されたメモリ空間の初期値を指定することに注意してください。このプロセスは変数の初期化と呼ばれます。
int値を出力します
int 型の値は、print() 関数を使用して出力できます。printf() と print() の違いは、f が改行を意味することです。
この関数では、%d は整数が出力される行上の位置を指定します。%d は、 printf() が値を表示するために使用する形式を指定する変換仕様を表します。フォーマット文字列内の各 %d は、出力される変数リスト内の対応する int 値と一致します。この値は、int 型の変数、int 型の定数、または値が int 型であるその他の式にすることができます。プログラマは、変換命令の数が出力される値の数と同じであることを確認してください。コンパイラはこの種のエラーを捕捉しません。以下は「C Prime Plus」のprint()のデモ例です。
#include<stdio.h>
int main()
{
int ten = 10;
int two = 2;
printf("Doing it right: ");
printf("%d minus %d is %d\n", ten, 2 , ten - two);
printf("Doing it wrong: ");
printf("%d minus %d is %d\n", ten);//遗漏两个参数
return 0;
}
プログラムをコンパイルして実行すると、出力は次のようになります。
出力の最初の行では、最初の %d は int 型変数 ten に対応し、2 番目の%d は int 型定数 2 に対応し、3 番目の %d は int 型式 ten-two の値に対応します。
出力の 2 行目では、最初の %d は値 10 に対応しますが、次の 2 つの %d には値が指定されていないため、メモリ内の任意の値が出力されます。(プログラムを実行している別の人によって表示されるこれら 2 つの値は、出力例の値とは異なります。これは、メモリに格納されているデータが異なり、コンパイラがメモリの場所を異なる方法で管理するためです)
8進数と16進数を表示
異なる基数の数値を C プログラムで使用および表示できます。ベースが異なれば、必要な変換命令も異なります。
数値を 10 進数で表示するには、%d; を使用して数値を 8 進数で表示します。%o を使用します。数値を 16 進数で表示するには、%x を使用します。
さらに、各基数の接頭辞 0、0x、0X を表示するには、それぞれ %#o、%#x、%#X を使用します。栗をあげます:
#include<stdio.h>
int main()
{
int x = 100;
printf("dec = %d, octal = %o; hex = %x\n", x, x, x);
printf("dec = %d, octal = %#o; hex = %#x\n", x, x, x);
return 0;
}
出力は次のとおりです。
他の整数型
C 言語には、補助キーワードによって変更された 3 つの基本データ型 (short、long、unsigned) が用意されています。次の点に留意してください。
- short int 型 (short と省略できます) は、int 型よりも占有する記憶領域が少なく、領域を節約するために値が小さい状況でよく使用されます。int と同様に、short は符号付き型です。
- Long int または long は、int よりも多くの記憶領域を占有する可能性があり、より大きな数値に適しています。int と同様に、long も符号付き型です。
- Long Long int または Long Long (C99 標準に追加) は、long よりも多くのメモリ領域を占有する可能性があり、より大きな数値に適しています。このタイプは少なくとも 64 ビットを占有します。int と同様に、long long は符号付き型です。
- unsigned int または unsigned は、負でない値に使用されます。この型は、符号付き型とは異なる範囲を表します。たとえば、16 ビット unsigned int の許容値の範囲は、-32768 ~ 3276 ではなく、0 ~ 65535 です。符号を表すために使用されていたビットは、別の 2 進ビットを表すために使用されるようになったため、符号なし整数でより大きな数値を表すことができます。
- C90規格では、unsigned long intまたはunsigned intまたはunsigned shortが追加されました。Unsignedlonglongint または unsignedlonglong が C99 標準に追加されました。
- signed 型の前にキーワード signed を追加すると、signed 型の意図が強調されます。たとえば、short、short in、signed short、signed short、signed short int は同じ型を表します。
複数の整数型を使用する理由
short 型が int 型よりも占有するスペースが「少ない」と言われるのはなぜですか、また、なぜ int 型が long 型よりも占有するスペースが「少ない」と言われるのですか? C 言語では、short が int よりも多くの記憶領域を占有することはできず、long が int よりも少ない記憶領域を占有することはできないと規定されているだけだからです。この規定は、以前はさまざまなマシンに適応するために設けられていましたが、現在ではコンピュータは 64 ビット プロセッサを使用するのが一般的であり、64 ビット整数を格納するために Long Long 型が導入されました。現在、パーソナル コンピューターで最も一般的な設定は、long long が 64 ビット、long が 32 ビット、short が 16 ビット、int が 16 または 64 ビット (コンピューターの自然語長に応じて) を占めるというものです。原則として、これら 4 つのタイプは 4 つの異なるサイズを表しますが、実際には、いくつかのタイプ間に重複が存在することがよくあります。
C 標準では、基本データ型の最小許容サイズのみが指定されています。int にはたくさんの型があるので、unsigned 型を優先して選ぶことができます。このタイプの数値は、負の数はカウントされず、符号なしタイプはより大きな正の数を表すことができるため、テクノロジーでよく使用されます。
int型の値の範囲を超え、long型の値の範囲内の数値の場合はlong型を使用してください。ただし、long が int の大きな領域を占めるシステムの場合、long 型を使用すると計算速度に影響します。したがって、ロングタイプは必要時以外は使用しないでください。さらに、long 型と int 型が同じスペースを占めるマシン上でコードを記述する場合、本当に 32 ビット整数が必要な場合は、int 型の代わりに long 型を使用する必要があることに注意してください。このプログラムは 16 ビット マシンにも移植可能であり、正常に動作します。同様に、64 ビット整数が本当に必要な場合は、long long 型を使用する必要があります。
int が 32 ビットに設定されているシステムで 16 ビット値を使用する場合は、領域を節約するために short 型を使用する必要があります。通常、スペースの節約が大きな問題となるのは、システムで利用可能なメモリに比べて大きな整数配列をプログラムが使用する場合のみです。short 型を使用するもう 1 つの理由は、コンピューターの一部のコンポーネントが 16 ビットのハードウェア レジスタを使用していることです。
長い定数と長い長い定数
通常、プログラム コードで使用される数値は、100000 などの int 型で格納されます。大きな数値が int の範囲を超える場合、コンパイラはその数値を long int 型として扱います (この型が数値を表現できると仮定して)。 、数値が long を超える場合、コンパイラは unsigned int 型として扱います。
整数オーバーフローの例:
#include<stdio.h>
int main()
{
int i = 214783647;
unsigned int j = 4294967295;
printf("%d %d %d\n", i, i+1, j+2);
printf("%u %u %u\n", j, j+1, j+2);
return 0;
}
出力結果:
符号なし整数jを車の走行距離計と 考えることができます。表現できる最大値に達すると、再び開始点から開始されます。整数 i についても状況は同様です。それらの主な違いは、unsigned int 型の定数 j は最大値を超えると 0 から始まるのに対し、int 型の変数 i は -2147483648 から始まることです。i が対応するアナログが表現できる最大値を超える (オーバーフローする) 場合、システムはユーザーに通知しないことに注意してください。したがって、プログラミング時にはこのような問題に注意する必要があります。
オーバーフロー規約は未定義の動作であり、C 標準では符号付き型のオーバーフロー ルールが定義されていません。上で説明したオーバーフロー動作はより代表的なものですが、他の状況も発生する可能性があります。
unsign int 型の値を出力するには、%u 変換命令を使用し、long 型の値を出力するには、%ld 変換命令を使用します。
使用文字:char型
char 型は文字を格納するために使用されますが、技術的には char は整数型です。char型は実際には文字ではなく整数を格納するためです。コンピューターは数値エンコーディングを使用して文字を処理し、特定の整数を使用して特定の文字を表します。米国で最も一般的に使用されているエンコーディングは ASCII エンコーディングであり、ここでも同じことが当てはまります。
ASCII エンコードでは、整数 65 は大文字 A を表すため、文字 A を格納すると、実際には整数 65 が格納されます。
標準 ASCII コードの範囲は 0 ~ 127 で、7 桁の 2 進数のみで表現できます。通常、char 型は 8 ビットの記憶単位として定義されているため、標準の ASCII コードを収容するには十分です。他の多くのシステムでは、同じく 8 ビット表現範囲内の拡張 ASCII コードも提供しています。一般に、C 言語では、char 型がシステム (C 言語を実装するシステム) の基本文字セットを格納するのに十分な大きさであることが保証されます。
中国語の文字セット (GB 2312) など、多くの文字セットは 127 を超えます。商用 Unicode (Unicode) は、世界中の複数の文字セットを表現できるシステムを作成し、現在 110,000 を超える文字が含まれています。
char変数の宣言は他の変数と同様なので省略します。
文字定数と初期化
文字定数を文字「A」に初期化します。
char grade = 'A';
C言語では、シングルクォートで囲まれた単一の文字を文字定数と呼びます。コンパイラは「A」を見つけると、それを対応するコード値に変換します。一重引用符は必須です。
非印刷文字
一重引用符は文字、数字、句読点にのみ適用されます。ASCI テーブルを参照すると、一部の ASCII 文字が印刷できないことがわかります。たとえば、動作を表す文字 (バックスペース、改行、端末の呼び出し音、ビープ音など)。C 言語では、これらの文字を表現する 3 つの方法が提供されています。
最初の方法は以前に紹介したもので、ASCI コードを使用します。たとえば、ビープ音文字の ASCII 値は 7 なので、次のように記述できます。
char beep 7;
2 番目の方法は、特殊記号シーケンスを使用して特殊文字を表す方法です。これらのシンボル シーケンスはエスケープ シーケンスと呼ばれます。
ここで、エスケープ シーケンスを詳しく見てみましょう。C90 の新しいアラーム文字 (a) を使用して、可聴または可視のアラームが生成されるかどうかは、コンピュータのハードウェアによって決まります。最も一般的なアラームはビープ音です (一部のシステムでは、アラーム文字が機能しません)。C 標準では、アラート文字がアクティブな位置を変更してはならないと規定されています。標準におけるアクティブ位置とは、次の文字が表示される表示デバイス (スクリーン、テレタイプ、プリンターなど) 内の位置を指します。つまり、よく言われる画面カーソルの位置はアクティブ位置です。プログラムで画面にアラーム文字を出力すると、ビープ音が鳴りますが、画面カーソルは移動しません。
次のエスケープ文字 \b、\f、\n、\r、\t、および \v は、一般的に使用される出力デバイス制御文字です。
それらを理解する最良の方法は、アクティブなポジションへの影響を確認することです。
- フォーム フィード文字 (\£) は、アクティブな位置を次のページの先頭に移動します。
- 改行文字 (\n) は、アクティブな位置を次の行の先頭に移動します。
- キャリッジ リターン (\r) は、アクティブな位置を現在の行の先頭に移動します。
- 水平タブ文字 (\t) は、アクティブな位置を次の水平タブ ポイント (通常は 1 番目、9 番目、17 番目、25 番目などの文字位置) に移動します。
- 垂直タブ文字 (\v) は、アクティブな位置を次の垂直タブ ポイントに移動します。
次の 3 つのエスケープ シーケンス (\\、\'、\") は、\、'、" 文字を出力するために使用されます (これらの文字は文字定数の定義に使用され、直接使用される場合は printf() 関数の一部であるためです)混乱を引き起こす可能性があります)。栗をあげます:
如果想打印下面一行代码:
Gramps sez,"a is a backslash."
应这样编写代码:
printf ("Gramps sez,\"a \is a backslash.\"\n");
この例では、エスケープ シーケンスが一重引用符で囲まれていないのはなぜですか?
通常の文字であっても、エスケープシーケンスであっても、ダブルクォーテーションで囲まれた文字の集合であれば、シングルクォートで囲む必要はありません。二重引用符で囲まれた文字の集合を文字列と呼びます。この例では、他の文字 (G、x、a、m、p、s など) が単一引用符で囲まれていないことに注意してください。同様に、 printf("Hello!\007\n"); は文字とビープ音を出力し、 printf("Hello!7\n"); は Hello!7 を出力します。エスケープ シーケンスに含まれていない数値は、通常の文字として出力されます。
では、いつ ASCII コードを使用し、いつエスケープ シーケンスを使用するのでしょうか? エスケープ シーケンス ('\f' が使用されていると仮定) と ASCII コード ('\014') のどちらかを選択する場合は、前者 (つまり 'f') を選択します。この書き方は覚えやすいだけでなく、移植性も高くなります。·\f' は、ASCII コードを使用しないシステムでも有効です。
ASCII コードを使用したい場合、なぜ 032 ではなく \032' と書く必要があるのでしょうか? まず、\032' は、文字エンコーディングを使用するプログラマの意図をより明確に表現できます。次に、032 のようなエスケープ シーケンスは、printf("HelIo!\007\n"); のように C 文字列に埋め込むことができます (\007 が埋め込まれています)。
文字を印刷する
printf() 関数は c を使用して、印刷する文字を指定します。前に紹介したように、文字変数は実際には 1 バイトの整数値として格納されます。したがって、d 変換命令を使用して char 型変数の値を出力すると、整数が出力されます。c 変換仕様は、整数値に対応する文字を印刷するように printf() に指示します。栗をあげます:
//显示字符的代码编号
#include <stdio.h>
int main()
{
char ch;
printf("Please enter a character.\n");
scanf_s("%c", &ch); /*用户输入字符*/
printf("The code for %c is %d.\n", ch, ch);
return 0;
}
出力例: 小文字の s を出力し、s に対応するコード番号が 115 であることを示します。
プログラムを実行するときは、文字を入力した後に Enter キーまたは Return キーを押すことを忘れないでください。続いて、scanf() 関数はユーザーが入力した文字を読み取り、& 記号は入力された文字が変数 ch に代入されることを示します。次に、printf() 関数は ch の値を 2 回出力します。1 回目は文字 (コード内の数値 c に対応) を出力し、2 回目は 10 進整数値 (コード内の数値 d に対応) を出力します。 。printf() 関数の変換仕様は、データの保存方法ではなく、データの表示方法を決定することに注意してください。
Bool型Boolean型
C99 標準では、ブール値、つまり論理値 true と fa1se を表す Bool 型が追加されました。C 言語では値 1 を使用して true を表し、値 0 を使用して false を表すため、Bool 型は実際には整数型です。ただし、0 と 1 の場合は 1 ビットの記憶領域で十分であるため、原則として、必要な記憶領域は 1 ビットだけです。
移植可能な型: stdint.h および inttypes.h
常識にとらわれず、詳細は自分で検索できます。
Float、int和double
浮動小数点型は、小数を含む広範囲の数値を表すことができ、浮動小数点数の表現は科学的表記法に似ています (つまり、数値を表すために小数に 10 の累乗を掛けます)。この表記法は、非常に大きな数値または非常に小さい数値を表すためによく使用されます。栗をあげます:
C 標準では、float 型は少なくとも 6 桁の有効数字を表現できなければならず、値の範囲は少なくとも 10 のマイナス 37 乗から 10 の 37 乗までであると規定されています。前者の要件は、float 型が小数点以下の少なくとも 6 桁の有効数字 (33.333333 など) を正確に表現する必要があることを意味します。後者の規定は、太陽の質量 (2.030 キログラム)、陽子の電荷 (1.6e19 クーロン)、または国の借金などの数値を表すのに便利に使用されます。通常、システムは浮動小数点数を格納するために 32 ビットを使用します。8 ビットは指数の値と符号を表すために使用され、残りの 24 ビットは非指数部分 (仮数または有効数とも呼ばれます) とその符号を表すために使用されます。
提供されているもう 1 つの浮動小数点型は double (倍精度を意味します) です。double 型と f1oat 型の最小値の範囲は同じですが、有効数字 10 桁以上を表現できる必要があります。通常、double は 32 ビットではなく 64 ビットを占有します。一部のシステムでは、追加の 32 ビットすべてを非指数部の表現に使用します。これにより、有効桁数が増加する (つまり、精度が向上する) だけでなく、丸め誤差も減少します。他のシステムでは、より大きな指数に対応するために一部のビットを指数部に割り当て、表現可能な数値の範囲を広げます。いずれの場合も、double 値には標準の最小桁数を超える少なくとも 13 桁の有効数字が必要です。
3 番目の浮動小数点型は、double 型よりも高い精度の要件を満たすために、long double です。ただし、C は、long double 型が少なくとも double 型と同じ精度を持つことを保証するだけです。
sizeof() 関数
sizeof() は、指定された型のサイズをバイト単位で与える C 言語の組み込み演算子です。C99 と C11 は、sizeof の戻り値の型に一致する %zd 変換命令を提供します。C99 および C11 をサポートしていない一部のコンパイラでは、%zd の代わりに %u または lu を使用できます。
4. 文字列とフォーマットされた入出力
弦
文字列 (文字列) は、以下に示すように、1 つ以上の文字のシーケンスです。
"おやすみなさい"//
二重引用符は文字列の一部ではありません。二重引用符は、二重引用符で囲まれた内容が次の内容であることをコンパイラに伝えるだけです。文字列は、個々の文字を識別するために一重引用符が使用されるのと同じです。
char型配列とnull文字
C 言語には文字列を格納するための特別な変数型はなく、文字列は char 型の配列に格納されます。配列は連続した記憶ユニットで構成され、文字列内の文字は隣接する記憶ユニットに格納され、各ユニットには 1 文字が格納されます。
そして、配列の末尾の文字\0。これはヌル文字で、C 言語が文字列の終わりをマークするために使用します。NULL文字は数字の 0 ではなく、ASII コード値が 0 (または同等) である非印刷文字です。C の文字列は null で終了する必要があります。これは、配列の容量が、格納される文字列の文字数より少なくとも 1 大きくなければならないことを意味します。
配列
では、配列とは何でしょうか? アレイは、連続したストレージユニットの行と考えることができます。より正式には、配列は同じタイプのデータ要素の順序付けされたシーケンスです。
char name [40];
名前の後の角括弧は、これが配列であることを示し、角括弧内の 40 は配列内の要素の数を示します。char は各要素の型を示します。変数と配列の宣言の違いを示す例を示します。
文字列は複雑に見えます。まず配列を作成し、文字列内の文字を 1 つずつ配列に入力し、最後に \0 を忘れずに追加する必要があります。幸いなことに、コンピュータはこれらの詳細を自ら処理できます。
文字列を使用します。
次のプログラムを実行して、文字列を操作するプロセスを体験してください。
/*praisel.c--使用不同类型的字符串*/
#include <stdio.h>
#define PRAISE "You are an extraordinary being."
int main(){
char name[40];
printf("What's your name?\n");
scanf("%s", name);
printf("Hello,%s,\n%s\n", name, PRAISE);
return 0;
}
%s は printf() に文字列を出力するように指示します。また、プログラムでは 2 つの文字列を出力する必要があるため、%s が 2 回表示されます。1 つは名前配列に格納され、もう 1 つはマクロ定義 PRAISE で表されます。その出力は次のように表現されます。
What's your name?
Angela Plains
Hello,Angela.
You are an extraordinary being.
自分で文字列の末尾に null 文字を置く必要はありません。scanf() は入力を読み取るときにこれを行います。文字列定数 PRAISE の末尾に NULL 文字を追加する必要はありません。#define ディレクティブについては後ほど説明しますが、PRAISE の後の二重引用符で囲まれたテキストが文字列であることがわかりました。コンパイラは最後に null 文字を追加します。これは重要ですが、scanf() は Angela Plains の Angela のみを読み取り、最初の空白 (スペース、タブ、または改行) に遭遇すると入力の読み取りを停止することに注意してください。したがって、scanf() は、Angela と Plains の間のスペースを読み取るときに停止します。一般に、%s 変換命令によれば、scanf() は文字列内の 1 つの単語のみを読み取り、文全体を読み取ることはありません。
文字列と文字
文字列定数"x" は文字定数'x'とは異なります。1 つの違いは、「x」が基本型 (char) であるのに対し、 「 x 」は派生型 (char 配列) であることです。2 番目の違いは、「x」が実際には 2 つの文字、「x」とヌル文字 \で構成されていることです。 0。
strlen() 関数
ここでは、配列によく使用される関数を追加します。上でオブジェクトのサイズをバイト単位で与える sizeof() 演算子について説明しました。一方、strlen() 関数は文字列内の文字の長さを返します。1 バイトに 1 文字が格納されるため、2 つのメソッドを文字列に適用すると同じ結果が得られると思われるかもしれませんが、そうではありません。栗をあげます:
/*praise2.c*/
//如果编译器不识别%zd,尝试换成%u或%lu.
#include <stdio.h>
#include <string.h>
/*提供strlen()函数的原型*/
#define PRAISE "You are an extraordinary being."
int main()
{
char name[40];
printf("What's your name?\n");
scanf("%s", name);
printf("Hello,%s,%s\n", name, PRAISE);
printf("Your name of %zd letters occupies %zd memory cells.\n",
strlen(name), sizeof name);
printf("The phrase of praise has %zd letters ",
strlen(PRAISE));
printf("and occupies zd memory cells.\n", sizeof PRAISE);
return 0;
}
ANSI 以前の C コンパイラを使用している場合は、次の行を削除する必要があります。
#include <string.h>
string.h ヘッダー ファイルには、strlen() などの複数の文字列関連の関数プロトタイプが含まれています。(ちなみに、ANSI 以前の UNIX システムの中には、string.h の代わりに strings.h を使用するものもあります。これには、いくつかの文字列関数の宣言も含まれています)。
一般に、C では関数ライブラリ内の関連する関数を 1 つのカテゴリにグループ化し、関数の種類ごとにヘッダー ファイルを提供します。たとえば、printf() と scanf() はどちらも標準入出力関数であり、stdio.h ヘッダー ファイルを使用します。string.h ヘッダー ファイルには、strlen() 関数とその他の文字列関連関数 (文字列コピー関数や文字列検索関数など) が含まれています。
上記の例では、2 つのメソッドを使用して非常に長い printf() ステートメントを処理していることに注意してください。方法 1 は、printf() ステートメントを 2 行に分割することです (引数の間で 2 行に分割できますが、二重引用符で囲まれた文字列の途中で分割しないでください)。 方法 2 は、2 つの printf() ステートメントを使用することです。コンテンツの行。2 番目の printf() ステートメントでのみ改行文字 (\n) を使用します。aプログラムを実行すると、対話型出力は次のようになります:
あなたの名前は何ですか?
ジャック
こんにちは、ジャック。あなたは特別な存在です。4
文字のあなたの名前は 40 個のメモリ セルを占有します。
賞賛のフレーズは 31 文字で、32 個のメモリ セルを占有します。
sizeof 演算子は、name 配列に 40 個の格納場所があることを報告します。ただし、Jack の格納には最初の 4 つのセルのみが使用されるため、strlen() の結果は、4.name 配列の 5 番目のセルに null 文字が格納され、strlen() ではカウントされません。
PRAISE の場合、strlen() を使用すると、文字列内の文字数 (スペースと句読点を含む) も計算されます。
ただし、sizeof 演算子は文字列の末尾にある非表示の null 文字を考慮するため、より大きな数値を与えます。プログラムは文字列用にどのくらいのスペースを確保するかをコンピューターに明示的に指示しないため、二重引用符内の文字数をカウントする必要があります。
定数と C プリプロセッサ
非常に一般的な定数は pi=3.14115926 です。
circumference = 3.14159 * diameter;
この例では、定数 pi を実際の値を入力して使用できます。ただし、この場合はシンボリック定数を使用する方がよいでしょう。つまり、コンピュータは次のステートメントを使用して、後で実際の値への置換を完了します:
円周 = pi * 直径;
なぜ記号定数を使用する方が良いのでしょうか? まず、定数名は数値よりも多くの情報を伝えます。次の 2 つのステートメントを比較してください:
owed = 0.015 * housevalue;
owed = Taxrate * housevalue;
非常に長いプログラムを読むと、2 番目のステートメントが表す意味がより明確になります。
また、プログラム内の複数の場所で定数が使用されている場合、その値を変更する必要がある場合があります。結局のところ、税率は通常変動します。プログラムでシンボリック定数を使用している場合、シンボリック定数を変更するだけでよく、プログラム内で定数が使用されている場所を探して 1 つずつ変更する必要はありません。
では、シンボリック定数はどのように作成するのでしょうか? 1 つの方法は、変数を宣言し、その変数を目的の定数に設定することです。次のように書くことができます:
float taxrate;
taxrate = 0.015;
これにより、シンボル名が提供されますが、税率は変数であり、プログラムがその値を誤って変更する可能性があります。C 言語もより優れたソリューションを提供します。つまり、C プリプロセッサは定数の定義にも使用できます。プログラムの先頭に次の行を追加するだけです。
#definepredirective
#define TAXRATE 0.015
プログラムをコンパイルすると、プログラム内のすべての TAXRATE が 0.015 に置き換えられます。このプロセスはコンパイル時置換と呼ばれます。プログラムを実行すると、プログラム内のすべての置換が完了します。通常、この方法で定義された定数は、マニフェスト定数とも呼ばれます。これはプリプロセッサによって処理される置換メカニズムであるため、末尾にセミコロンがないことに注意してください。ここでは、TAXRATE は大文字にする必要があります。記号定数を表すのに大文字を使用するのが C 言語の一貫した伝統だからです。このように、プログラム内ですべて大文字の名前を見ると、これが変数ではなく記号定数であることがすぐにわかります。大文字の定数はプログラムの可読性を向上させるためのものであり、記号定数を表すためにすべて小文字の記号が使用されている場合でも、プログラムは正常に動作します。それにもかかわらず、初心者は定数を大文字にする良い習慣を身につけるべきです。
また、一般的には使用されない命名規則もあります。これは、名前の前に c または k を付けて定数を示します (たとえば、c_level1 または k_line)。シンボリック定数の命名規則は変数の場合と同じです。大文字、小文字、数字、アンダースコアを使用できますが、最初の文字を数字にすることはできません。
さらに、#define ディレクティブでは、前者には一重引用符、後者には二重引用符を使用して、文字定数と文字列定数を定義することもできます。
#define BEEP '\a'
#define TEE 'T'
#define ESC '033'
#define OOPS "Now you have done it!"
#define プレディレクティブには等号が必要ないことに注意してください。
/*错误的格式*/
#define TOES = 20
如果这样做,替换TOES的是= 20,而不是20。这种情况下,下面的语句:
digits = fingers + TOES;
将被转换成错误的语句:
digits = fingers + = 20;
const修飾子
C90 標準では、変数を読み取り専用に制限するために使用されるconstキーワードが追加されています。(変数は非定数です)
const int MONTHS = 12;
//MONTHS在程序中不可更改,值为12.
これにより、MONTHS は読み取り専用の値になります。つまり、MONTHS を計算に使用して 12 を出力することはできますが、MONTHS の値は変更できません。const は #define よりも柔軟に使用できますが、const に関する内容については後述します。
明示的な定数
C ヘッダー ファイルlimits.hおよびfloat.h は、それぞれ整数型と浮動小数点型のサイズ制限に関連する詳細を提供します。
各ヘッダー ファイルは、実装で使用する明示的な定数のセットを定義します。たとえば、limits.h ヘッダー ファイルには次のようなコードが含まれています。
#define INT MAX 32767
#define INT MIN -32768
これらの明示的な定数は、int 型が表現できる最大値と最小値を表します。
システムが 32 ビット int を使用する場合、ヘッダー ファイルはこれらの明示的な定数に異なる値を提供します。プログラムにlimits.hヘッダー・ファイルを組み込む場合は、次のコードを記述できます。
printf("Maximum int value on this system =&d\n",INT MAX);
システムが 4 バイト int を使用する場合、limits.h ヘッダー ファイルは 4 バイト int に準拠する INT MAX および INT MIN を提供します。
次の図は、limits.h にある明示的な定数の一部を示しています。
同様に、FLT DIG や DBL DIG などのいくつかの明示的な定数も float.h ヘッダー ファイルで定義されており、それぞれ float 型と double 型の有効桁数を表します。次の表は、float.h 内の明示的な定数の一部を示しています (テキスト エディターを使用して、システムで使用される float.h ヘッダー ファイルを開いて表示できます)。表にリストされているものはすべて float 型に関連しています。明示的な定数名の LT をそれぞれ DBL および LDBL に置き換えて、それぞれ double および 1 ong double 型に対応する明示的な定数を表します(この表では、システムが浮動小数点数を表すために 2 のべき乗を使用していると想定しています)。
//defines.c--使用limit.h和float头文件中定义的明示常量
#include <stdio.h>
#include <limits.h> //整型限制
#include <float.h> //浮点型限制
int main()
{
printf("Some number limits for this system:\n");
printf("Biggest int: &d\n", INT MAX);
printf("Smallest longlong: $11d\n", LLONG MIN);
printf("One byte &d bits on this system.\n", CHAR BIT);
printf("Largest double:e\n", DBL MAX);
printf("Smallest normal float:%e\n", FLT MIN);
printf("float precision &d digits\n", FLT DIG);
printf("float epsilon=号e\n", FLT EPSILON);
return 0;
}
printf() と scanf() および I/O 関数
printf() 関数と scanf() 関数を使用すると、ユーザーはプログラムと通信できます。これらは入出力関数、または単に I/O 関数です。これらはC言語の入出力関数であるだけでなく、最も汎用性の高い関数です。以前は、これらの関数は、C ライブラリの他の関数と同様、C 言語定義の一部ではありませんでした。元々、C は入出力の実装をコンパイラの作成者に任せており、コンパイラの作成者は入出力を特定のマシンに適切に一致させることができました。その後、互換性の問題を考慮して、各コンパイラは異なるバージョンの printf() と scanf() を提供するようになりました。ただし、バージョン間には相違点が存在する場合があります。C90 および C99 標準では、これらの関数の標準バージョンが指定されており、本書はこの標準に従っています。
printf() は出力関数、scanf() は入力関数ですが、これらはほぼ同じように機能します。どちらの関数もフォーマット文字列とパラメータ リストを使用します。
プリントフ()
printf() 関数にデータの印刷を要求する命令は、印刷するデータのタイプと一致する必要があります。たとえば、整数を出力する場合は %d を使用し、文字を出力する場合は %c を使用します。これらのシンボルは変換仕様と呼ばれ、データを表示可能な形式に変換する方法を指定します。
printf() 関数の形式は次のとおりです。
printf(格式字符串,待打印项1,待打印项2,...);
印刷対象項目 1、印刷対象項目 2、…はすべて印刷対象項目です。変数、定数、または印刷前に評価される式を指定することもできます。フォーマット文字列には、印刷する各項目の変換命令が含まれている必要があります。たとえば、次のステートメントを考えてみましょう。
printf("The &d contestants ate $f berry pies.\n",number,pies);
フォーマット文字列は二重引用符で囲まれた内容です。上記のステートメントのフォーマット文字列には、印刷される 2 つの項目 (数字と詩) に対応する 2 つの変換命令が含まれています。フォーマット文字列には、次の 2 つの異なる情報が含まれています。
- 印刷される実際の文字。
- 変換手順。
フォーマット文字列内の変換命令は、後続の各項目と一致する必要があります。この基本要件を忘れると、重大な結果が生じる可能性があります。次のようには決して書かないでください:
printf("スコアはイカ%d、ナメクジ%dでした。\n",score1);
ここで、2 番目の %d はどの項目にも対応しません。システムが異なれば、結果も異なります。ただし、この問題に対する最良のシナリオは、無意味な値を取得することです。
フレーズや文章のみを印刷する場合は、変換命令を使用する必要はありません。データを印刷するだけの場合は、説明文を追加する必要はありません。
printf("Farewell! thou art too dear for my possessing,\n");
printf("%c%d\n" , '$' , 2 * cost);
2 番目のステートメントに注目してください。出力されるリストの最初の項目は変数ではなく文字定数であり、2 番目の項目は乗算式です。これは、printf() が変数、定数、式のいずれであっても、値を使用することを示しています。printf() 関数は % 記号を使用して変換命令を識別するため、% 記号の出力が問題になります。% 記号を単独で使用すると、コンパイラーは変換文字が欠落していると判断します。解決策は非常に簡単で、2 つの % 記号を使用するだけです。
pc = 2 * 6:
printf("Only %d%% of Sally's gribbles were edible.\n", pc);
输出结果:Only 12% of Sally's gribbles were edible.
printf()の変換仕様修飾子
注 型の移植性
sizeof 演算子は、型または値のサイズをバイト単位で返します。これは何らかの形式の整数である必要がありますが、標準では値が符号なし整数であることのみが指定されています。さまざまな実装では、unsigned int、unsigned long、さらには unsigned longlong にすることができます。したがって、printf() 関数を使用して sizeof 式を表示する場合は、システムに応じて %u、%lu、または %llu を使用できます。これは、現在のシステムでの使用状況を調べ、プログラムを別のシステムに移植する必要がある場合は変更を行うことを意味します。このため、C ではより移植性の高い型が提供されています。まず、stddef.h ヘッダー ファイル (stdio.h ヘッダー ファイルをインクルードするときに含まれる) は、size_t を、sizeof を使用してシステムによって返される型として定義します。これは、基になる型と呼ばれます。次に、printf() は z 修飾子を使用して、対応する型の印刷を示します。同様に、C では ptrdiff_t 型と t 修飾子も定義して、システムが 2 つのアドレスの差分に使用する基礎となる符号付き整数型を表します。
float 型パラメータの変換に注意してください。
浮動小数点型の場合、double 型とlong double 型の変換命令はありますが、float 型の変換命令はありません。これは、K&RC では式やパラメータ内の float 型の値が自動的に double 型に変換されるためです。一般に、ANSIC は float を double に自動的に変換しません。ただし、float 型の引数が自動的に double に変換されると想定している多数の既存のプログラムを保護するために、printf() 関数内の float 型のすべての引数 (明示的なプロトタイプを使用しないすべての C 関数に有効) は依然としてそのままです。自動的に double 型に変換されます。したがって、K&RC も ANSI C も、float 型の値に固有の変換命令を示していません。
フィールド幅プログラム
//defines.c--使用limit.h和float头文件中定义的明示常量
#include <stdio.h>
#define PAGES 959
int main()
{
printf("*%d*\n", PAGES);
printf("*%2d*\n", PAGES);
printf("*%10d*\n", PAGES);
printf("*%-10d*\n", PAGES);
return 0;
}
输出结果;
*959*
*959*
* 959*
*959 *
修飾子のない最初の変換仕様 %d は、整数フィールド幅の変換仕様と同じ出力になります。デフォルトでは、修飾子のない変換命令は次のように出力されます。2 番目の変換記述は %2d で、それに対応する出力結果は 2 フィールド幅である必要があります。出力される整数は 3 桁であるため、フィールド幅は整数の長さに合わせて自動的に拡張されます。3 番目の変換の説明は %10d で、対応する出力結果の幅はスペース 10 個です。実際には、2 つのアスタリスクの間にはスペース 7 個と 3 桁があり、数値はフィールドの右側にあります。最後の変換記述は番号 -10d で、それに対応する出力結果も 10 スペース幅です。- マークは、出力される番号がフィールドの左側にあることを示します。それらの使用法に慣れると、出力形式を適切に制御できるようになります。PAGES の値を変更して、コンパイラが異なる桁の数値をどのように出力するかを確認してください。
浮動小数点バイト幅出力
//floats.c--一些浮点型修饰符的组合
#include <stdio.h>
int main()
{
const double RENT = 3852.99;//const变量
printf("*%f*\n", RENT);
printf("*%e*\n", RENT);
printf("*%4.2f*\n", RENT);
printf("*%3.1f*\n", RENT);
printf("*%10.3f*\n", RENT);
printf("*%10.3E*\n", RENT);
printf("*%+4.2f*\n", RENT);
printf("*%010.2f*\n", RENT);
return 0;
}
输出结果如下:
*3852.990000*
*3.852990e+03*
*3852.99*
*3853.0*
* 3852.990*
* 3.853E+03*
*+3852.99*
*0003852.99*
この例の最初の変換指定は %f です。このデフォルトの場合、フィールド幅と小数点以下の桁数は両方ともシステムのデフォルト設定です。つまり、フィールド幅は、印刷される数値と小数点以下 6 桁を収容するのに必要な桁数です。
2 番目の変換仕様は %e です。デフォルトでは、コンパイラは小数点の左側に 1 桁、小数点の右側に 6 桁を出力します。これでは数字が多すぎます。解決策は、小数点の右側に表示する桁数を指定することです。これは、プログラム内の次の 4 つの例で行われます。4 番目と 6 番目の例では出力が丸められていることに注意してください。さらに、6 番目の例では、e の代わりに E が使用されます。
7 番目の変換仕様には + 記号が含まれており、出力される値の前に代数記号 (+) が追加されます。0 フラグを指定すると、フィールド要件を満たすために、出力される値の先頭に 0 が付加されます。変換記述 %010.2f の最初の文字はマークであり、ピリオド (.) の前とマークの後の数字 (この例では 10) が指定されたフィールド幅であることに注意してください。
文字列形式の出力
/*stringf.c -- 字符串格式*/
#include <stdio.h>
#define BLURB "Authentic imitation!"
int main()
{
printf("[%2s]\n", BLURB);
printf("[%24s]\n", BLURB);
printf("[%24.5s]\n", BLURB);
printf("[%-24.5s]\n", BLURB);
return 0;
}
输出结果:
[Authentic imitation!]
[ Authentic imitation!]
[ Authe]
[Authe ]
最初の変換仕様は番号 2S ですが、フィールドは文字列内のすべての文字を収容できるように拡張されることに注意してください。また、精度によって印刷される文字数が制限されることにも注意してください。.5 は printf() に 5 文字のみを印刷するように指示します。さらに、 - フラグを指定すると、テキストが左揃えで出力されます。
変換記述の意味
変換命令の意味を詳しく見てみましょう。変換命令 コンピュータにバイナリ形式で格納されている値を文字列(文字列)に変換して表示します。たとえば、数値 76 は、コンピュータの内部記憶形式にバイナリ01001100として保存されます。 %d 変換命令は、これを文字 7 と 6 に変換し、76 として表示します。 %x 変換命令は、同じ値 ( 01001100 )を変換します。 Number メソッド 4c:%c 変換命令は、01001100を文字 L に変換します。コンピューターの最下層は 2 進数で格納されるため、同じ 2 進数でも変換命令を通じて異なる文字を表すことができ、表現できる数値の可能性が高まります。
変換すると、元の値が変換後の値に変換されると読者に誤解を与える可能性があります。実際、変換仕様は変換仕様を指し、%d は「指定された値を 10 進整数リテラルに変換して出力する」ことを意味します。
変換の不一致
前に強調したように、変換仕様は出力される値の型と一致する必要があります。通常、複数のオプションがあります。たとえば、int 型の値を出力する場合は、%d、%x、または %o を使用できます。これらの変換命令はすべて、int 型の値を出力するために使用できます。違いは、値を表す方法にあります。同様に、double 型の値を出力する場合は、%f、%e、または %g を使用できます。
変換仕様が出力される値の型と一致しない場合はどうなりますか? 不一致によって引き起こされるいくつかの問題は、前の章で紹介されました。マッチングは非常に重要であり、留意する必要があります。次のプログラムは、不一致の整数変換の例をいくつか示します。
/*intconv.c--一些不匹配的整型转换*/
#include <stdio.h>
#define PAGES 336
#define WORDS 65618
int main()
{
short num = PAGES;
short mnum = -PAGES;
printf("num as short and unsigned short: %hd %hu\n", num, num);
printf("-num as short and unsigned short:%hd %hu\n", mnum, mnum);
printf("num as int and char: %d %c\n", num, num);
printf("WORDS as int,short,and char: %d %hd %c\n", WORDS, WORDS, WORDS);
return 0;
}
输出结果:
num as short and unsigned short: 336 336
-num as short and unsigned short:-336 65200
num as int and char: 336 P
WORDS as int,short,and char: 65618 82 R
出力の最初の行では、num 変数に対応する変換命令は、%hd と %hu の出力結果が両方とも 336 であることを示しています。これには何の問題もありません。ただし、2 行目の mnum 変数に対応する変換命令 %u (符号なし) は、予期された 336 ではない 65200 を出力します。これは、参照システムでの signed short int 型の値の表現方法によるものです。
まず、short int のサイズは 2 バイトです。次に、システムは 2 の補数を使用して符号付き整数を表します。この方法では、0 ~ 32767 の数値はそれ自体を表し、32768 ~ 65535 の数値は負の数を表します。このうち、65535 は -1 を意味し、65534 は -2 を意味します。したがって、-336 は 65200 (つまり、65536-336) として表されます。したがって、signed int として解釈される場合、65200 は -336: を表し、unsigned int として解釈される場合、65200 は 65200 を表します。注意してください!数値は 2 つの異なる値に解釈できます。すべてのシステムが負の整数を表すためにこのメソッドを使用するわけではありませんが、数値と記号を区切るために %u 変換仕様を使用することを期待しないでください。
行 3 は、255 を超える値が文字に変換された場合に何が起こるかを示しています。私たちのシステムでは、short int は 2 バイト、char は 1 バイトです。printf() が c を使用して 336 を出力するとき、336 を格納する 2 バイトの最後の 1 セクションだけを調べます。この切り捨ては、整数を 256 で除算し、余りのみを保持することと同じです。この場合、余りは 80 で、対応する ASCII 値は文字 P です。専門用語では、この数値は「modulo256」(modulo256)、つまり数値を 256 で割って余りを求めると解釈されます。
最後に、このシステムの short int 型の最大の整数 (32767) よりも大きい整数 (65618) を出力します。今回は、コンピュータはモジュロ計算も実行しました。このシステムでは、数値 65618 を 4 バイトの int 型の値として格納する必要があります。HD 変換命令を使用して印刷する場合、printf() は最後の 2 バイトのみを使用します。これは、65618 を 65536 で割った余りに相当します。ここで、余りは 82 です。負の数の格納方法により、余りが 32767 ~ 65536 の範囲にある場合、負の数として出力されます。整数サイズが異なるシステムの場合、対応する処理動作は似ていますが、結果の値は異なる場合があります。