序文
少し前に、簡単なモードと難しいモードの両方で、ポインター ペン テストの問題をいくつか集めました。夏休みにやるつもりだったんですが、長引いてしまい、お気に入りに灰が残ってしまいました 最近、夜空を眺めていたら、今日も空が晴れていました 背伸びしました指を動かしてみると、今日はこの問題に適した天気であることがわかりました。お気に入りに忘れられていた演習をすぐに掘り出しました。今日はそれを打ち破ってみましょう!
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;
}
解析:
int* ptr = (int*)(&a + 1);
&a は配列全体のアドレスを取り出すことを意味し、&a+1 は配列全体をスキップすることを意味し、配列の末尾の後の ptr のアドレスを取り出します。
printf("%d %d", *(a + 1),*(ptr-1));
a は配列の最初の要素のアドレスを表し、a+1 は配列の 2 番目の要素のアドレスを表します。(a+1) は配列の 2 番目の要素 (2) を表し、
ptr-1 はアドレスを表します配列の最後の要素のアドレスである要素へのアドレスは 5 のアドレスです、 (ptr-1) は 5
図面分析:
筆記試験2
コードは以下のように表示されます
//由于还没学习结构体,这里告知结构体的大小是20个字节
struct Test
{
int Num;
char* pcName;
short sDate;
char cha[2];
short sBa[4];
}* p = (struct Test*)0x100000;
//假设p 的值为0x100000。 如下表表达式的值分别为多少?
//已知,结构体Test类型的变量大小是20个字节
int main()
{
printf("%p\n", p + 0x1);
printf("%p\n", (unsigned int)p + 0x1);
printf("%p\n", (unsigned int*)p + 0x1);
return 0;
}
分析する
printf("%p\n", p + 0x1);
p は構造体ポインタ、+1 は構造体をスキップします。p
構造体のサイズは 20 バイトであることがわかっているため、0x100000+20=0x100014 になります。16 進数に変換されることに注意してください。
printf("%p\n", (unsigned int)p + 0x1);
p の構造体型は強制的に符号なし長整数に変換され、これはアドレスではなく整数になります。整数 + 1 は +1 であり、1+1=2 と同じなので、0x100000+1 =0x100001
printf("%p\n", (unsigned int*)p + 0x1);
pは、構造体ポインターと同じ方法で符号なし整数ポインターに強制され、+1 は 4 バイトをスキップします。0x100000+4=0x100004
筆記試験の質問3
int main()
{
int a[4] = {
1, 2, 3, 4 };
int* ptr1 = (int*)(&a + 1);//4后面
int* ptr2 = (int*)((int)a + 1);//
printf("%x,%x", ptr1[-1], *ptr2);
return 0;
}
解析:
int* ptr1 = (int*)(&a + 1);
&a+1 は配列全体をスキップします
int* ptr2 = (int*)((int)a + 1);
a は本来最初の要素のアドレスで、a の型は int* ですが、(int)a は a を強制的に整数に変換することを意味するため、(int)+1 は要素をスキップするのではなく、整数+1
printf("%x,%x", ptr1[-1], *ptr2);
ptr1[-1]=ptr1+(-1)=*(ptr1-1)、ptr1-1 は要素アドレスに前方アクセスし、逆参照すると 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) };
カンマ式: 左から右に計算され、式全体の結果は最後の式の結果になります。
注: ここには 3 つのカンマ式があります。最大値は 1 つの括弧内で計算されるため、
実際には int a[3][2] になります。 ]={1,3,5};
int* p;
p = a[0];
a[0]は2次元配列の1行目の配列名で、sizeof内にa[0]だけが入っているわけではなく、&装飾もないので1行目の先頭要素のアドレスになります、p は整数ポインタで、アドレス [0] を格納します。
printf("%d", p[0]);
p[0]=*(p+0)=*p
*p は、p に格納されているアドレス (1) が指す要素を逆参照します。
図面分析:
筆記試験の質問5
int main()
{
int a[5][5];//五列五行
int(*p)[4]; //*p是一个数组指针,存放数组地址的指针,4行4列
p = a;//把a赋给p
printf("%p, %d\n",&p[4][2] - &a[4][2],&p[4][2] - &a[4][2]);
return 0;
}
解析:
したがって、&p[4][2] - &a[4][2] は -4 になります。
%p はアドレスを出力するためのものであり、補数を計算してから 16 進数に変換する必要があることに注意してください。
10000000000000000000000000000100 -4 元のコード
11111111111111111111111111011 逆コード
1111 1111 1111 1111 1111 1111 1111 1100 補数コード
FFFFFFFC //fourバイナリ 16 進数ビットに変換されたビット
%p は -4 を出力します アドレスは 0xFFFFFFFC
要約する
以上が本日公開する筆記試験問題5問です。