8 つのポインター ペン テストの質問でポインターを克服

著者ホームページ: paper jie's blog_CSDNブログ - C言語、アルゴリズム詳細分野ブロガー

この記事の著者:皆さんこんにちは、私はpaper jieです。この記事を読んでいただきありがとうございます。3つの会社を構築することを歓迎します。

この記事は、大学生やプログラミング初心者向けに丁寧に作成されたコラム「C言語」に収録されています。著者は多大な費用(時間とエネルギー)を費やして作成しており、C 言語の基礎知識はすべて持っていますので、読者の皆様のお役に立てれば幸いです。

その他コラム:「C言語のシステム解析」、「アルゴリズムの詳細解説」、「C言語の文法」

コンテンツの共有:この号では、ポインターを克服するために 8 つのテスト問題が使用されます。おじいちゃんの皆さん、小さなベンチを移動して座ってください。

    -------- 998はいらない、98もいらない、ボタン1つで3回、3回買っても損はしない、騙されない

序文

ポインタに関する前回の記事では、複数のテスト問題を使用して、ポインタと配列の関係を包括的かつ多面的に説明しました。この記事では、ポインターを総合的かつ多面的に理解するために、ポインター ペン テストの古典的な 8 つの問題を使用します。

最初の質問

答えはいくらですか?なぜこの答えになるのでしょうか?

int main()
{
 int a[5] = { 1, 2, 3, 4, 5 };
 int *ptr = (int *)(&a + 1);
 printf( "%d,%d", *(a + 1), *(ptr - 1));
 return 0;
}

分析する

まず、a は配列の最初の要素のアドレス、&a は取り出したアドレス全体であることがわかります。したがって、a+1 は 2 番目の要素のアドレスであり、逆参照は 2 です。&a+1は配列全体をスキップするもので、5要素以降の強制型はint、つまりその後ろのアドレスの加減算の単位がint型になっています。ptr は &a+1 のアドレスなので、ptr-1 は 5 のアドレスを指す int 型の forward を減算することになり、逆参照は 5 になります。

 

2番目の質問

p の値が 0x100000 であるとします。次の表の式の値は何ですか?
構造体テストタイプの変数サイズは20バイトであることがわかっています


struct Test
{
 int Num;
 char *pcName;
 short sDate;
 char cha[2];
 short sBa[4];
}*p;

int main()
{
 printf("%p\n", p + 0x1);
 printf("%p\n", (unsigned long)p + 0x1);
 printf("%p\n", (unsigned int*)p + 0x1);
 return 0;
}

分析する

プロンプトから、これがサイズ 20 バイト、アドレス 0x100000 の構造体ポインター型であることがわかります。0x1 は p+1 で、サイズ 20 の構造体タイプを追加します。つまり、0x100000+20=0x100014 です。unsigned long p は p を整数型に変換し、整数型に 1 を加算することは 1 を加算します。結果は 0x100000+1=0x100001 unsigned int* p は p をポインタ型に変換するため、p+1 は次のようになります。ポインター サイズ 0x100000+ 4=0x100004 を追加します

3番目の質問

答えはなんですか?なぜそうなるのでしょうか?

int main()
{
 int a[4] = { 1, 2, 3, 4 };
 int *ptr1 = (int *)(&a + 1);
 int *ptr2 = (int *)((int)a + 1);
 printf( "%x,%x", ptr1[-1], *ptr2);
 return 0;
}

分析する

a は最初の要素のアドレスです。&a+1 は配列全体のアドレスを取り出します。int*(&a+1) は &a+1 の型を int* の型に変換します。ptr[-1] は次のようになります。 *(ptr- 1) として理解され、ptr は &a+1 であるため、ptr-1 は int* 型のサイズを減算することになるため、要素 4 のアドレスでの逆参照は 4 int a になります。アドレス a を変換することになります。を整数に変換し、その整数に 1 を加算することは 1 を加算することです。また、メモリ内のアドレスがバイトであることもわかっています。ここで 1 を加算すると、a+1 が指す内容は 00 ~ 02 0x02000000 になります。

4番目の質問

答えはなんですか?なぜ?

#include <stdio.h>
int main()
{
 int a[3][2] = { (0, 1), (2, 3), (4, 5) };
 int *p;
 p = a[0];
 printf( "%d", p[0]);
 return 0;
}

分析する

観察すると、配列に () があるため、これはカンマ式であり、右側の値は予約されているため、() の値は 1、2、3 は 0 で埋められていることがわかります。その後に 0 が続くので、配列は次のようになります。 中央のレイアウトは、描画後の外観です。

p は a[0] のアドレスで、a[0] は表される最初の行です。a[0] は最初の行の配列名として理解できるため、a[0] は最初の要素のアドレスです。逆参照は 1

5番目の質問

答えはいくらですか?なぜそうなるのでしょうか?

int main()
{
 int a[5][5];
 int(*p)[4];
 p = a;
 printf( "%p,%d\n", &p[4][2] - &a[4][2], &p[4][2] - &a[4][2]);
 return 0;
}

  分析する

a 配列は 5 行 5 列の 2 次元配列で、a は開始要素のアドレス、a のアドレスを p に代入し、q は配列ポインタ、p の型は int[4] です。
したがって、pを加算するたびに要素が4つスキップされるので、p[4]は*(p+4)となります。 pのアドレスは絵を描いた後のアドレスで、その2つのアドレスを引いたものが次の数値となります。 &p[4][2 ]-&a[4][2]=-4
コンピューターに保存されているのは補数コードであることはわかっています。100 が%P
出力される場合、補数コードは直接住所として出力され、%d または - 4 で出力されます。




 

6番目の質問

答えはいくらですか?なぜそうなるのでしょうか?

int main()
{
 int aa[2][5] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
 int *ptr1 = (int *)(&aa + 1);
 int *ptr2 = (int *)(*(aa + 1));
 printf( "%d,%d", *(ptr1 - 1), *(ptr2 - 1));
 return 0;
}

分析する

aa は最初の要素のアドレス、つまり 1 行目のアドレス & aa は 2 次元配列全体のアドレスを取り出します。 ptr1=
&aa+1 &aa+1 は int* 型に変換されるため、ptr-1 は次のようになります。 int* 型の size を減算すると、この時点で ptr は 10 要素のアドレスを指し、10

aa+1 は最初の行のアドレスに 1 を加えた 2 行目のアドレスになります。aa の型が次のようになります。 +1 も int* なので、前の int* は役に立ちません。これは次のように理解できます: int*ptr=*(aa+1)、*(aa+1) は aa[1] として理解できます。aa[1] は 2 行目の配列名で、最初の行のアドレスです。要素、および ptr==*(aa+1)==aa[1] であるため、ptr-1 は要素 5 を指しているため、逆参照は 5 です。

 

7番目の質問

答えはいくらですか?なぜそうなるのでしょうか?

#include <stdio.h>
int main()
{
 char *a[] = {"work","at","alibaba"};
 char**pa = a;
 pa++;
 printf("%s\n", *pa);
 return 0;
}

分析する

配列 a に格納されている char* 型の要素を知る必要があります。これは、work、at、および alibaba の最初の要素のアドレスです。

2 次ポインターを使用して、a のアドレスを保管します。pa==a、pa++==a++、a は最初の要素のアドレス、pa++==a++ は 2 番目の要素のアドレスです。

*pa は at の最初の文字のアドレスです。%s はこの文字列を最初の文字のアドレスまで出力します。

 

質問8

答えはいくらですか?なぜそうなるのでしょうか?

int main()
{
 char *c[] = {"ENTER","NEW","POINT","FIRST"};
 char**cp[] = {c+3,c+2,c+1,c};
 char***cpp = cp;
 printf("%s\n", **++cpp);
 printf("%s\n", *--*++cpp+3);
 printf("%s\n", *cpp[-2]+3);
 printf("%s\n", cpp[-1][-1]+1);
 return 0;
}

分析する

c 配列には文字列の最初の要素のアドレスが格納され、cp 配列には最初の要素のアドレスが格納され、cpp には cp のアドレスが格納されます。ここでも 1 つの点に注意する必要があります。++ と -- は値を直接変更するため、後続の計算に影響します。

 


おすすめ

転載: blog.csdn.net/paperjie/article/details/131350491