<筆記試験問題>ポインタ

コンテンツ

1.筆記試験の質問1:

2.筆記試験の質問2:

3.筆記試験の質問3:

4.筆記試験の質問4:

5.筆記試験の質問5:

6.筆記試験の質問6:

7.筆記試験の質問7:

8.筆記試験の質問8:


1.筆記試験の質問1:

#include<stdio.h>
int main()
{
	int a[5] = { 1, 2, 3, 4, 5 };
	int* ptr = (int*)(&a + 1);
	printf("%d,%d", *(a + 1), *(ptr - 1));
	return 0;
}
//程序的结果是什么?

  •  解析:

  • *(ptr-1)

&aは配列全体のアドレスを取り出すことを意味し、&a + 1は配列全体をスキップします。タイプは&a:int(*)[5]、タイプはまだint(*)[5]、キャスト&a + 1 int *の場合、それをptrに割り当て、ptrは&a + 1のアドレスを指し、ptr-1は前の要素のアドレスであり、*(ptr-1)を逆参照して5を取得します。

  • *(a + 1):

aは配列名の最初の要素1のアドレスを表し、+ 1は要素2のアドレスを表し、逆参照*(a + 1)は2です。

2.筆記試験の質問2:

#include<stdio.h>
struct Test
{
	int Num;
	char* pcName;
	short sDate;
	char cha[2];
	short sBa[4];
}*p;
//假设p 的值为0x100000。 如下表表达式的值分别为多少?
//已知,结构体Test类型的变量大小是20个字节
int main()
{
	printf("%p\n", p + 0x1);
	printf("%p\n", (unsigned long)p + 0x1);
	printf("%p\n", (unsigned int*)p + 0x1);

	printf("%x\n", p + 0x1);
	printf("%x\n", (unsigned long)p + 0x1);
	printf("%x\n", (unsigned int*)p + 0x1);

    //%p以地址的形式打印,不省略0
    //%x就是打印16进制,省略0
	return 0;
}

  • 解析:
  • p + 0x1:

整数ポインター(int *)+ 1は4バイトをスキップし、文字ポインター(char *)+ 1は1バイトをスキップし、構造ポインターp + 1は構造サイズ(20バイト)をスキップする必要があります。20の16進数は0x000014です。 、および追加後は0x100014です。

  • (unsigned long)p + 0x1:

pは元々構造体へのポインタでしたが、強制的にunsigned long型に変換すると、unsigned integer型になり、ポインタではなくなります。unsignedinteger型なので、次のように扱われます。数値であり、1を追加した後、直接追加するだけです。つまり、0x100001

  • (unsigned int *)p + 0x1:

pは整数ポインターに強制変換され、整数ポインター+1は4バイトをスキップし、4を加算すると0x100004になります。

3.筆記試験の質問3:

#include<stdio.h>
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;
}

  • 解析:
  •  ptr1 [-1]:

&aは配列のアドレスを取り出し、&a + 1は配列全体をスキップし、それをint *にキャストして、ptr1に割り当てます。このとき、ptr1のアドレスは&a + 1であり、ptr[-1]は次のようになります。 *(ptr1-1)、ptr1-1のアドレスは図のようになり、逆参照された結果は4になります。

  • * ptr2:

配列名aは最初の要素のアドレスを表し、強制型は値である整数に変換されます。1を追加すると、1バイトが追加されます。メモリはバイト単位のデータに変換される必要があり、要素1は4です。セクション、それがリトルエンディアンの場合、aのアドレスが0x10で、10進数に変換されて16、プラス1が17、16進数が0x11で、ptr2のアドレスを見つけて、参照解除するだけでさらに4バイトにアクセスできます。 2000000として印刷できます。プロセスを図に示します

4.筆記試験の質問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;
}

  •  解析:

この質問には落とし穴があり、コンマ式がテストされます。int a [3] [2] = {(0、1)、(2、3)、(4、5)};このコードは次のように変換できます。 int a [3] [2] = {1、2、5};この配列は3行2列で、a [0]は最初の行の配列名、配列名は最初の要素のアドレスを表します。 a [0]は、最初の行の最初の行を表します。要素のアドレス、つまり、pが指す位置、p [0] = *(p + 0)= * p 、およびpは1を取得するために参照を解除します。 。

5.筆記試験の質問5:

#include<stdio.h>
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 [4] [2]:

&a [4] [2]は、図に示すように、行5と列3のアドレスを表します。

  • &p [4] [2]:

 pは配列ポインタであり、pが指すことができる配列は4要素であり、p + 1は16バイトである4つの整数をスキップします、p [4] [2] ---> *(*(p + 4)+2 )、aは配列の配列名、つまり最初の要素のアドレスであり、aをpに割り当てます。また、図に示すように、pはアドレスを指します。p + 1は4つの要素の配列をスキップし、+ 4の位置は図に示すようになります。*(p + 4)は、黄色のボックス*(p + 4)、*(p + 4)+2は、図のように2つの要素が指す位置をスキップし、それを逆参照して、要素を取得します。

  • &p [4] [2]-&a [4] [2] 2つの整数型のアドレスを引くと、中央の要素数は4になります。これは、小さいアドレスが大きいアドレスを減らすため、次の形式で印刷するためです。 %dは-4
  • そして、%pの形式で印刷することは、アドレスを印刷することであり、補数を印刷するだけです。

-4の補数:1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1100

16進印刷に変換されるのはFFFFFFFFFFFF FFFC

6.筆記試験の質問6:

#include<stdio.h>
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;
}

  • 解析:
  • *(ptr1-1):

&aaは2次元配列のアドレスを意味し、&aa + 1は、2次元配列全体を図に示す位置にスキップし、整数ポインターに強制してptr1に割り当てることを意味します。ptr1-1のアドレス図に示すように、それを逆参照します。これは10番です。

  • *(ptr2-1):

aaは、2次元配列の最初の要素の最初の行のアドレスを示す配列名です。aa+ 1は、図に示すように最初の行を2番目の行にスキップしてから、*(aa + 1)を逆参照します。配列名の2行目を取得します。最初の要素のアドレス、つまり要素6のアドレスがptr2に強制的に割り当てられ、ptr2-1が前方に移動し、それを逆参照して5を取得します。

7.筆記試験の質問7:

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

  • 解析:

 paのタイプはchar*です。1を追加すると、char *の要素をスキップし、図に示す位置をポイントし、* paを逆参照してaのアドレスを取得し、%sが\0に逆方向にアクセスして停止します。 。それはです。

8.筆記試験の質問8:

#include<stdio.h>
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;
}

  • 解析:
  • ** ++ cpp:

 ++cppはchar**要素のアドレスを図に示されている位置にスキップし、*++cppを逆参照して要素c+2を取得し、c+2はcの3番目の要素のアドレスです。 referenceはpのアドレスを取得し、\ 0、つまりPOINTまで%sの形式で出力します。

  • *-* ++ cpp + 3:

++cppは別のchar*要素をスキップしてアイコンの位置に移動し、*++cppを逆参照してc+1を取得します。-*++cppはc+1-1 = cになります。このとき、cはc配列名です。最初の要素のアドレス、次に間接参照*-* ++ cppを使用してEのアドレスを取得し、次に+3を使用して2番目のEをポイントし、ERを%sで出力します。

  •  * cpp [-2] + 3:

  * cpp [-2]は**(cpp-2)+3です。cpp-2が指す位置を図に示します。*(cpp-2)を逆参照してc + 3を取得し、次に**(cpp-2)を逆参照してFのアドレスを取得し、+3がSを指します。次に、%sSTを出力します。

  • cpp [-1] [-1] + 1:

 cpp [-1] [-1] + 1は*(*(cpp-1)-1)+1であり、cpp-1の位置は図に示すとおりであり、間接参照はc + 2になり、マイナス1はc+になります。 1、次に間接参照*(*(cpp-1)-1)を使用してNのアドレスを取得し、さらに1を使用してEを指すと、%sはEWを出力します。

おすすめ

転載: blog.csdn.net/bit_zyx/article/details/122590914