コンテンツ
1つ:自動
1.1ローカル変数とグローバル変数
ローカル変数とグローバル変数の定義:
ローカル変数:コードのブロック内に含まれる変数は、ローカル変数と呼ばれます。ローカル変数は一時的なものです。コードブロックに入ると、ローカル変数が自動的に形成され、コードブロックを出ると、自動的に解放されます。[インターネット上の多くの人々は、関数の変数はローカル変数であると言います。それは間違いではありませんが、ステートメントは不正確です]
グローバル変数:すべての関数の外部で定義された変数は、グローバル変数と呼ばれます。グローバル変数はグローバルです。
コードブロック: {}で囲まれた領域はコードブロックと呼ばれます
変数の範囲-追加コンテンツ:
スコープの概念:通常アクセスできる変数のコード領域を指します
ローカル変数:このコードブロック内でのみ有効
グローバル変数:プログラムの実行中は有効です
変数の存続期間-追加コンテンツ:
ライフサイクルの概念:変数の定義から解放までの時間範囲を指します。いわゆる解放とは、開かれて「解放された」空間を指します。
ローカル変数:コードブロックに入り、ローカル変数を形成し[スペースを開く]、コードブロックを終了し、ローカル変数を「解放」します
グローバル変数:定義が完了した後、変数は実行中のプログラムのライフサイクル全体を通じて常に有効です。
特殊なケース:同じ名前のローカルとグローバルがローカルよりも優先されます
#include <stdio.h>
int g_x = 100; //全局变量
int main()
{
int g_x = 10; //局部变量,与全局同名
printf("g_x:%d\n", g_x); //输出的是局部,也就是局部和全局同名的时候,优先局部。所以,强烈不建议这样干。
return 0;
}
1.2自動車関連
使い方:
通常、コードブロックで定義されている変数、つまりローカル変数は、デフォルトでautoによって変更されますが、autoは通常省略されます。
すべての変数はデフォルトで自動ですか?
いいえ、通常はローカル変数を変更するために使用されます
ちょっと立ち止まってください。後で見るもの、ローカル変数、自動変数、一時変数はすべて同じものです。まとめてローカル変数と呼びます
例えば:
#include<stdio.h>
int main()
{
for (int i = 0; i < 5; i++)
{
printf("%d\n", i);
if (1)
{
auto int j = 1;
printf("before=%d\n", j);
j++;
printf("after1=%d\n", j);
}
}
return 0;
}
要約:
//グローバル変数ではなく、ローカル変数の変更にのみ使用できます。
//このキーワードは少し古いので、必要なければ大きな問題にはなりません
2:登録(最速のキーワード)
実際、CPUは主にコンピューティングを担当するハードウェアユニットですが、操作を容易にするために、一般的な最初のステップはメモリからCPUにデータを読み取ることであるため、CPUには一定の一時的なデータストレージ容量が必要です。 。
注:CPUは現在計算する必要がないため、特定のデータをCPUに読み込みますが、これは遅すぎます。
したがって、最近のCPUでは、レジスタと呼ばれる一連のハードウェアが統合されて一時データが格納されます。
ストレージピラミッド:
レジスターの知識:
現在、ストレージハードウェアのセットがCPUに統合されていることがわかっている限り、ハードウェアの詳細は無視できます。このハードウェアのセットはレジスタと呼ばれます。
レジスターの存在の本質:
ハードウェアレベルでは、コンピューターの計算効率を向上させます。メモリからデータを読み取る必要がないためです。
変更された変数を登録します。
効率を向上させる目的を達成するために、変更された変数をCPUレジスタ領域に配置してみてください
では、どのような変数を登録できるのでしょうか。
1.ローカル(グローバルではCPUレジスタが長時間占有されます)
2.書き込まれません(書き込むには、メモリに書き戻す必要があります。後で読み取りと検出が必要な場合は、レジスタの意味は何ですか?)
3.高周波で読み取られます(効率が向上します)
4.使用する場合は、レジスタ数に限りがありますので、あまり使用しないでください。
上記に加えて、別の点があります。つまり、レジスタによって変更された変数はアドレスを取得できません(レジスタ領域に配置されているため、アドレスはメモリ関連の概念です)
#include<stdio.h>
int main()
{
register int pass = 100;
printf("%d\n", pass);
//printf("%d\n", &pass); // err
//一旦使用register寄存器,可以正常访问,但不能使用&
return 0;
}
私の意見:コンパイラはすでに非常にインテリジェントであり、人間よりもコードを最適化できるため、このキーワードについて心配する必要はありません。初期のコンパイラは、手動で最適化するためにレジスタを手動で指定する必要がありましたが、現在はそうではありません。
3:静的
はじめに:まず、特定のファイルの下にある他のファイルの内容(グローバル変数または関数)にアクセスする状況
高速ファイルにアクセスするときは、最初に宣言してからアクセスして、コンパイラがエラーを報告しないようにする必要があることは誰もが知っています。
例えば:
test.cファイルで次の変数を定義する場合
この時点で、main.cファイルでアクセスする必要があります。アクセスする前に宣言する必要があります。そうしないと、コンパイラでエラーが発生します。
声明である限り、externを持参するのが最善です
//変数宣言はexternである必要があります//関数宣言はexternであることが推奨されます
//宣言と定義の一貫性を可能な限り維持するようにしてください
次のことがわかります。
1.ファイル間でグローバル変数にアクセスできますか?できる!
2.ファイル間で関数にアクセスできますか?できる!
グローバル変数または関数がファイル間でアクセスされるのではなく、このファイル内でのみアクセスされるようにすることは可能ですか?
この時点で、重要なキーワードstaticが導入されています。
test.cファイルのg_val変数 を静的に変更すると、 main.cファイルにエラーが報告されますが、test.c内のg_valにアクセスすることは可能です。
結論1:静的はグローバル変数を変更します。グローバル変数はこのファイル内でのみアクセスでき、外部ファイルから直接アクセスすることはできませんが、関数を介して間接的にアクセスできます
現時点では問題ありませんが、関数を静的に変更するとコンパイラもエラーになります
結論2:静的に変更された関数。この関数はこのファイル内でのみアクセスでき、他の外部ファイルでは直接アクセスできません。
しかし、そのような状況があります。test.cファイルで別の関数を定義し、次のようなshow関数をネストします。
この時点で、 main.cファイルで次の操作を実行して実行し、問題がないことを確認します。
上記の簡単な例の操作を通じて、次の結論を導き出すことができます。静的プロジェクトのメンテナンスはセキュリティ保証を提供します
静的はグローバル変数と関数を変更し、範囲を制限します
静的に変更されたローカル変数:
最初にコードを見てください:
#include<stdio.h>
static void fun()
{
int i = 0;
i++;
printf("%d ", i);
}
int main()
{
int i = 0;
for (i = 0; i < 10; i++)
{
fun();
}
}
iローカル変数、ローカル一時、関数が呼び出されたときにスペースを開いて初期化し、関数が終了したときにスペースを解放します
static int i = 0;を取ると、結果は1〜10で見たいものになります。
static int i = 0;
この時点で、staticを追加した後、楽しみの実行中にiが解放されないことを見つけるのは難しくありません!!!
例でそれを証明してください:!!!
結論3: 静的はローカル変数を変更し、一時変数をグローバル変数に変換するローカル変数のライフサイクルを変更しますが、スコープは変更されませんが、ライフサイクルは変更されました
上記の静的な結論を要約します。
結論1:静的はグローバル変数を変更します。グローバル変数はこのファイル内でのみアクセスでき、外部ファイルから直接アクセスすることはできませんが、関数を介して間接的にアクセスできます
結論2:静的に変更された関数。この関数はこのファイル内でのみアクセスでき、他の外部ファイルでは直接アクセスできません。
結論3: 静的はローカル変数を変更し、一時変数をグローバル変数に変換するローカル変数のライフサイクルを変更しますが、スコープは変更されませんが、ライフサイクルは変更されました
4:sizeof
役割のサイズ:スペースを開くときに対応するタイプのサイズを決定します
#include<stdio.h>
int main()
{
printf("%d\n", sizeof(char)); //1
printf("%d\n", sizeof(short)); //2
printf("%d\n", sizeof(int)); //4
printf("%d\n", sizeof(long)); //4
printf("%d\n", sizeof(long long)); //8
printf("%d\n", sizeof(float)); //4
printf("%d\n", sizeof(double)); //8
return 0;
}
ここにいくつかの特別なケースがあります:
int a = 10;
printf("%d\n", sizeof(a)); // 1 4
printf("%d\n", sizeof(int)); // 2 4
printf("%d\n", sizeof a); // 3 4
//printf("%d\n", sizeof int); // 4 err
これらの4つのラベルのうち、4つ目は間違っており、他の実行結果は4です。
3番目のラベルから、基本的な事実を描くことができます。sizeofは関数ではなく、キーワードまたは演算子です。
sizeofは、カスタムタイプのサイズを見つけることができます。
#include<stdio.h>
int main()
{
int* p = NULL;
int arr[10];
int* test[3];
printf("%d\n", sizeof(p)); // 4
printf("%d\n", sizeof(arr)); // 40
printf("%d\n", sizeof(test)); // 12
return 0;
}