C言語のポインタに関するいくつかのトピック(2)

この記事は前のブログの続きです

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を取得します。

おすすめ

転載: blog.csdn.net/Naion/article/details/122590308