[C言語ファンデーション10-ポインタ(1)]


序文

この記事は、ポインタ関連のコンテンツの研究を開始します。主なコンテンツは次のとおりです。

  • ポインタとは
  • ポインターとポインターの種類
  • ワイルドポインタ
  • ポインタ演算
  • ポインタと配列
  • 二次ポインタ
  • ポインタの配列

1.ポインタとは何ですか?

ポインタを理解するための2つのポイント:

  • 通常、話し言葉で話されるポインタは、通常、メモリアドレスを格納するために使用される変数であるポインタ変数を参照します。
  • ポインタは、メモリ内の最小単位の番号、つまりアドレスです。

1.1ポインタ変数

&(アドレス演算子)を使用して、変数のメモリの実際のアドレスを取り出し、そのアドレスを変数(ポインター変数)に格納できます。

int main()
{
    
    
	int a = 1;//在内存中开辟一块空间
	//a变量占用4个字节的空间,这里是将a的4个字节的第一个字节的地址存放在p变量中,p就是一个指针变量
	int* pa = &a;//这里我们对变量a,取出它的地址,可以使用&操作符
	printf("%p\n", &a);
	printf("%p\n", pa);
	a = 10;
	printf("%p\n", &a);
	return 0;
}

メモリと監視を使用して、&aとpaの変更を確認
ここに画像の説明を挿入
します。下の画像を参照してください。

  • &aは変数aのアドレスです:0x00CFFEE0
  • paはポインタ変数であり、格納される値は変数aのアドレスです:0x00CFFEE0

変数は4バイトのスペースを占有します。次の図では、占有のアドレスがメモリ内で4バイトを占有し、00 000001を格納していることがわかります。

ここに画像の説明を挿入
メモリ表示列の数は自分で調整できます。4列は4バイトの行を意味します。下の図を参照してください
ここに画像の説明を挿入
。10をaに再割り当てすると、変数aの値は変わりますが、アドレスは変更されません。
ここに画像の説明を挿入
ここに画像の説明を挿入
したがって、ポインタ変数、アドレスを格納するために使用される変数。(ポインタに格納されている値はアドレスとして扱われます)。

1.2ポインタは、メモリ内の最小単位の数です

  • ポインタは、メモリ内の最小単位の数であり、バイトです。
  • 専門家による慎重な計算と重み付けの結果、対応するアドレスにバイトを与える方が適切であることがわかりました。
  • 32ビットマシンの場合、32個のアドレスラインがあると仮定すると、各アドレスラインがアドレス指定時に高レベル(高電圧)と低レベル(低電圧)を生成すると仮定すると、それは(1または0)、32アドレスです。この回線によって生成されるアドレスは次のとおりです。
00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000001
...
11111111 11111111 11111111 11111111

メモリの最小単位はバイトであり、対応するアドレスを次の図に示します。
ここに画像の説明を挿入
したがって、32ビットマシンには32乗の2つのアドレスがあります。各アドレスはバイトを識別し、次のように指定できます。

2^32バイト==2^ 32/1024 KB == 2 ^ 32/1024/1024 MB == 2 ^ 32/1024/1024/1024 GB == 4 GB

アドレス指定には4GBの空き容量があります。同様に、64ビットマシンに64のアドレスラインが与えられている場合、8GBのスペースをアドレス指定できます。

  • 32ビットマシンでは、アドレスは32 0または1のバイナリシーケンスであるため、アドレスは4バイトのスペースに格納する必要があるため、ポインタ変数のサイズは4バイトである必要があります。
  • 64ビットマシンでは、64のアドレス行があり、アドレスを格納するためのポインタ変数のサイズは8バイトです。
  • ポインタはアドレスを格納するために使用され、アドレスはアドレス空間の一部の一意のマークです
  • ポインタのサイズは、32ビットプラットフォームでは4バイト、64ビットプラットフォームでは8バイトです。
int main()
{
    
    
	int a = 10;
	int* pa = &a;
	char ch = 'a';
	char* pc = &ch;
	printf("%d\n", sizeof(pa));//4
	printf("%d\n", sizeof(pc));//4
	return 0;
}

上記の例は、ポインタ変数のタイプに関係なく、そのサイズが4バイトであることを示しています。アドレスは32ビット01で表され、ポインタ変数はアドレスを格納する変数であるため、格納するには4バイトが必要です。彼のタイプに関係なく。
ここに画像の説明を挿入

2.ポインタとポインタの種類

変数には、整数、浮動小数点数など、さまざまなタイプがあります。そのポインタのタイプも次のとおりです。

int num = 10;
p = #//num的地址保存到 p 

&num(numのアドレス)をpに保存するために、pがポインター変数であることがわかっているので、そのタイプは何ですか?ポインタ変数に対応するタイプを与えます

char *pc = NULL;
int *pi = NULL;
short *ps = NULL;
long *pl = NULL;
float *pf = NULL;
double *pd = NULL;

ポインタは次のように定義されます:type + *

  • char *型ポインタは、char型変数のアドレスを格納するために使用されます。つまり、アドレス内の変数はchar型であり、1バイトを占め、アドレス自体は4バイトです。
  • short *型ポインタは、short型変数のアドレスを格納するために使用されます。つまり、アドレス内の変数はshort型であり、1バイトを占有し、アドレス自体は4バイトです。
  • int *型のポインタは、int型の変数のアドレスを格納することです。つまり、アドレス内の変数はint型であり、4バイトを占め、アドレス自体は4バイトです。

2.1ポインタ±タイプ

int main()
{
    
    
	int n = 10;
	char *pc = (char*)&n;
	int *pi = &n;
	printf("%p\n", &n);
	printf("%p\n", pc);
	printf("%p\n", pc+1);
	printf("%p\n", pi);
	printf("%p\n", pi+1);
	return 0;
}

ポインターのタイプによって、ポインターが前進または後退する距離(距離)が決まります。

  • int * +1後方、intクラスの次の変数のアドレスに移動、4バイト移動
  • char * +1後方、次のchar型変数のアドレスに移動、1バイト移動
  • アドレスへのポインタに格納されている値のタイプであるポインタのタイプ

ここに画像の説明を挿入

2.2ポインタの間接参照

ポインターのタイプは、ポインターを逆参照するときに持つ権限の量を決定します(数バイトで動作可能)

2.2.1int*型の逆参照

int main()
{
    
    
	int a = 0x11223344;
	int* pa = &a;
	*pa = 0;
	return 0;

int *へのポインタを間接参照すると、4バイトにアクセスできます。
ここに画像の説明を挿入
ここに画像の説明を挿入

2.2.2char*型の逆参照

int main()
{
    
    
	int a = 0x11223344;
	char* pa = (char*)&a;//&a是int*,所以在这里强制转换
	*pa = 0;

	return 0;
}

char *へのポインタ逆参照は、 1バイトにしかアクセスできません。

ここに画像の説明を挿入

ここに画像の説明を挿入

3.ワイルドポインタ

ワイルドポインタは、ポインタが指していることがわからない場所です(ランダム、正しくない、指定されていない)

3.1ワイルドポインタの原因

3.1.1ポインタが初期化されていません

int main()
{
    
    
	int *p;//局部变量指针未初始化,默认为随机值
	*p = 20;
	return 0;
}

3.1.2ポインターの範囲外アクセス

int main()
{
    
    
	int arr[10] = {
    
    0};
	int *p = arr;
	int i = 0;
	for(i=0; i<=11; i++)//超过数组的元数个数
	{
    
    
		//当指针指向的范围超出数组arr的范围时,p就是野指针
		*(p++) = i;
	}
	return 0;
}

3.1.3ポインタが指すスペースを解放します

int* test()
{
    
    
	int a = 10;
	printf("%d\n", a);
	return &a;//开辟的空间已经释放了
}
int main()
{
    
    
	int* p = test();//函数调用结束后,开辟的内存空间释放了
	*p = 100;
	return 0;
}

3.2ワイルドポインタを回避する方法

  • ポインタの初期化
  • 範囲外のポインタに注意してください
  • スペースへのポインターは、NULLに設定されていても解放されます
  • ローカル変数のアドレスを返さないようにする
  • 使用前にポインタの有効性を確認してください
int main()
{
    
    
	int *p = NULL;//初始化
	//....
	int a = 10;
	p = &a;
	if(p != NULL)
	{
    
    
		*p = 20;
	}
	return 0;
}

要約する

この記事では、ポインターの内容の一部を学習しました。次の記事では、ポインターの内容について引き続き学習します。

おすすめ

転載: blog.csdn.net/taibudong1991/article/details/123788274