この記事は前のブログの続きです
C言語ポインタのいくつかのトピック(1)_Naionのブログ-CSDNブログhttps://blog.csdn.net/Naion/article/details/122548523引き続きいくつかのトピックを実行しましょう。
筆記試験問題1:
int main()
{
int a[5] = { 1, 2, 3, 4, 5 };
int *ptr = (int *)(&a + 1);
printf( "%d,%d", *(a + 1), *(ptr - 1));
return 0;
}
//程序的结果是什么?
解析:
2.aは配列の最初の要素のアドレスであり、+ 1は配列の2番目の要素のアドレスを取得します。*では、要素2を取得します。
5.&a、配列のアドレスを取得し、+ 1、配列全体をスキップします。強制後、ptrの位置は配列の後ろにあります。-1は5を指します。つまり、-1は5のアドレス*では、5を取得します。
筆記試験の質問2:
struct Test
{
int Num;
char *pcName;
short sDate;
char cha[2];
short sBa[4];
}*p;
//假设p 的值为0x100000。 如下表表达式的值分别为多少?
//已知,结构体Test类型的变量大小是20个字节
int main()
{
p = (struct Test*)0x100000;
printf("%p\n", p + 0x1);
printf("%p\n", (unsigned long)p + 0x1);
printf("%p\n", (unsigned int*)p + 0x1);
return 0;
}
解析:
ここでは、この構造のサイズを20バイトと想定し、p値を0x100000としています。想定されているため、実行すると結果が異なる場合がありますが、違いは同じです。
ここでの0x100014.pは、構造体のアドレスです。これは+1です。つまり、構造体全体のサイズを20バイトスキップしてから、20を16進数(0x100014)に変換します。
0x100001.pは、符号なし長整数に強制的に変換され、次に+1(値+1)(0x100000)に変換されます。
0x100004.pはunsignedintポインターに強制変換され、+1はこのintポインターのサイズである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;
}
解析:
4.&aはこの配列のアドレスであり、+ 1の場合、この配列をスキップします。ここで、ポインターの形式で記述されたptr1 [-1]は*(ptr1 -1)、つまり4です。
2000000(リトルエンディアンモード)aは、配列の最初の要素のアドレスであり、(int)は、型を10進数に変換するように強制します。+1、つまり、10進数に1を加算してから、に変換します。 16進数。intは4バイトスキップすることに注意してください。
質問4:
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;
}
解析:
ff ff ff fc。図に示すように、-4を16進数に変換できます。
-4.示されているように。
質問5:
#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次元配列全体の要素は1、3、5です。p= a [0]、最初の行を取得してから、 p [0]、これは最初の行の最初の要素です。
筆記試験の質問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;
}
解析:
10.&aaは2次元配列のアドレスを取得し、次に+1し、2次元配列をスキップして、int *型に変換し、ptr1ポインターを使用して受信します。ptr1-1は要素10のアドレスです。その場合、*は要素10です。
5.aaは配列の最初の要素のアドレスです。2次元配列の場合は最初の行です。次に+1し、最初の行をスキップして2番目の行に移動します。このアドレスはptr2によって受信されます。ポインタ。-1、5のアドレスで、*、要素5が取り出されます。
筆記試験の質問7:
#include <stdio.h>
int main()
{
char *a[] = {"work","at","alibaba"};
char**pa = a;
pa++;
printf("%s\n", *pa);
return 0;
}
解析:
図に示すように:
筆記試験の質問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;
}
解析:
ポインタは画像を指しています:(優先順位に注意してください!)
POINT.cpp ++、c + 2、次に*、値POINTを内部で取得します。
ER.cppは、前の印刷のアドレス、次に++、c + 1のアドレス、次に*を継承して、c + 1のアドレスを取得し、次に-を継承して、c+1がcに変更されたことを示します。つまり、そのポイントはNEWではありませんが、ENTER、+ 3、Eのアドレスに到達し、*、ERです。
ST。*cpp[-2] +3、これは* *(cpp-2)+ 3.cpp-2と同等であり、c + 3に移動し、次に*、c + 3のアドレスを取得し、次に* 、次にFIRSTを取得し、次に+3を取得します。Sに到達したら、STを取得します。
EW. *(*(cpp-1)-1)+ 1、-1に相当し、次にc + 2になり、次に*、c + 2になり、次に-1になり、次にc+2がc+になります。 1、次に*、次にNEWを取得し、次に+1を取得するとEWを取得します。