1. ポインタとは何ですか?
ポインタは、変数のアドレスを格納するために使用される変数タイプです。基本データ型 (整数、文字など) や複合データ型 (配列、構造体など) を含む、任意のデータ型を指すことができます。ポインタを介して、特定のメモリ アドレスに格納されているデータに間接的にアクセスしたり、データを変更したりできます。
- ポインタとはメモリ内の最小単位の番号、つまりアドレスです。
- 通常の話し言葉で言うポインタは、通常、メモリアドレスを格納するために使用される変数であるポインタ変数を指します。
要約: ポインタはアドレスです。話し言葉におけるポインタは通常、ポインタ変数を指します。
ポインタ変数は、アドレスを格納するために使用される変数です。
ここでの質問は次のとおりです。
- 小型ユニットとはどのくらいの大きさですか? (1バイト)
- どのように対処すればよいでしょうか?
慎重な計算と検討の結果、1 つの対応するアドレスに 1 バイトを与えることがより適切であることがわかりました。
32 ビット マシンの場合、32 のアドレス ラインがあると仮定し、アドレス指定中に各アドレス ラインがハイ レベル (高電圧) とロー レベル (低電圧) を生成すると仮定すると (1 または 0)、32 生成さ
れる
アドレス住所行は次のようになります。
00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000001
…
11111111 11111111 11111111 11111111
ここには 2 の 32 乗のアドレスがあります。
各アドレスはバイトを識別し、(2^32Byte == 2^32/1024KB == 2^32/1024/1024MB == 2^32/1024/1024/1024GB == 4GB) 4G スペースを指定できます。同様に、64 ビット マシンには 264 個のアドレスがあります。
ここで私たちは次のように理解します。
- 32 ビット マシンでは、アドレスは 32 個の 0 または 1 で構成されるバイナリ シーケンスであり、アドレスは 4 バイトの空間に格納する必要があるため、ポインター変数のサイズは 4 バイトにする必要があります。
- 64 ビット マシンの場合、アドレス行が 64 行ある場合、1 つのアドレスを格納するためのポインター変数のサイズは 8 バイトになります。
概要:
ポインタ変数はアドレスを格納するために使用され、アドレスはメモリ ユニットを一意に識別します。
2. ポインタとポインタの型
変数には整数、浮動小数点などのさまざまな型があることは誰もが知っています。ポインタには型がありますか? 以下のコードを見てみましょう。
int num = 10;
p = #
&num (num のアドレス) を p に保存するには、p がポインター変数であることがわかりますが、その型は何でしょうか? ポインタ変数に対応する型を与えます。
char *pa = NULL;
int *pb = NULL;
short *pc = NULL;
long *pd = NULL;
float *pe = NULL;
double *pf = NULL;
ここで、char* 型ポインタが char 型変数のアドレスを格納するために使用されていることがわかります。
short* 型ポインタは、short 型変数のアドレスを格納するために使用されます。
int* 型のポインタは、int 型の変数のアドレスを格納するために使用されます。
long* 型ポインタは、long 型変数のアドレスを格納するために使用されます。
float* 型ポインタは、float 型変数のアドレスを格納するために使用されます。
double* 型ポインタは、double 型変数のアドレスを格納するために使用されます。
これら 2 つの図から、ポインターのサイズはポインターの種類とは関係がなく、マシンのビット数にのみ関係していることがわかります。32 ビット マシンでは、ポインターのサイズは 4 バイトを占めます。 64 ビット マシンでは、8 バイトを占有します。
ポインタ型の意味は何ですか? 下を見てみましょう。
ポインターの種類によって、ポインターが前後に移動する距離 (距離) が決まることがわかります。pi は int 型であるため、pi+1 は 4 バイト移動され、pc は char 型であるため、pc は 1 バイトだけ移動されます。
3. ワイルドポインタ
ワイルド ポインターは、ポインターが指す場所が不明であることを意味します (ランダム、不正確、明確な制限がない)。ワイルド ポインターの原因:
1.ポインタが初期化されていない
#include <stdio.h>
int main()
{
int *p;//局部变量指针未初始化,默认为随机值
*p = 10;
return 0;
}
2. ポインタの境界外アクセス
#include <stdio.h>
int main()
{
int arr[10] = {
0};
int *p = arr;
int i = 0;
for(i=0; i<=11; i++)
{
*(p++) = i;//当指针指向的范围超出数组arr的范围时,p就是野指针
}
return 0;
}
3. ポインタが指すスペースを解放します。
#include <stdio.h>
int* test()
{
int a = 10;
return &a;
}
int main()
{
int* p = test();
printf("%d\n", *p);
return 0;
}
ワイルドポインタを回避する方法
- ポインタの初期化 (ポインタがどの値に初期化されるかわからない場合は、NULL に初期化できます)
- ポインタが範囲外になることに注意してください
- スペースを指すポインタは解放され、やがて NULL に設定されます。
- ローカル変数のアドレスを返さないようにする
- 使用する前にポインタの有効性を確認してください
4. ポインタ演算
- ポインタに整数を加算または減算すると、アドレスが前後に移動します。
- ポインタの絶対値からポインタを引いた値が、ポインタとポインタの間の要素の数になります。ポインタマイナスポインタの前提は、2 つのポインタが同じ空間を指しているということです。
5. ポインタと配列
配列名と配列の最初の要素のアドレスが同じであることがわかります。
結論: 配列名は配列の最初の要素のアドレスを表します。
配列名をアドレスとしてポインタに格納できるため、ポインタを使用して配列名にアクセスすることが可能になります。
したがって、p+i は実際にインデックス i を持つ配列 arr のアドレスを計算します。
その後、ポインタを介して配列に直接アクセスできます。
例えば:
6. セカンダリポインタ
ポインタ変数も変数です 変数にはアドレスがあります ではポインタ変数のアドレスはどこに格納されているのでしょうか?
答えはセカンダリ ポインタです。
セカンダリ ポインタの操作は次のとおりです。
- *ppa は ppa 内のアドレスを逆参照するため、検出されるのは pa です。 *ppa は実際に pa にアクセスします。
int b = 20;
*ppa = &b;//pa = &b; と同等
- **ppa は、最初に *ppa までの pa を検索し、次に pa: *pa を逆参照してから、a を検索します。
**ppa = 30;
// *pa = 30; と同等;
// a = 30 と同等;
7. ポインタ配列
ポインタの配列はポインタですか、それとも配列ですか?
答え: それは配列です。ポインタを格納する配列です。
配列 整数配列と文字配列についてはすでに知っています。
int arr1[5];
char arr2[6];
ポインターの配列はどのようなものですか?
int* arr3[5];//是什么?
arr3 は 5 つの要素を持つ配列で、各要素は整数ポインターです。