自学内容网 自学内容网

指针 + 数组 较为复杂凌乱的 【笔试题】

2024 - 10 - 10 - 笔记 - 25
作者(Author): 郑龙浩 / 仟濹(CSDN 账号名)

【指针 + 数组】的 各种题型(笔试题)

来自于鹏哥的网课,我做一下笔记

119. 【C语言进阶】笔试题详解(4)_哔哩哔哩_bilibili

① 题
#include <stdio.h>
int main()
{
    int a[5] = { 1, 2, 3, 4, 5 };
    //&a 是整个数组的地址,+1是跳过这个数组,所以该指针指向到了数组后面
    int* ptr = (int*)(&a + 1);
    //*(a + 1): a 为数组的首元素地址(第 0 个元素地址),a + 1 是数组第 1 个元素地址,解引用第 1 个元素地址得出的就是 第 1 个元素
    //ptr - 1: 上面知道了ptr指向的是数组的后边,那么 ptr - 1指向的就是数组的最后一个元素
    printf("%d, %d", *(a + 1), *(ptr - 1) );
    
    return 0;
}

打印结果:

2, 5

② 题

注:结构体大小是按照最大的成员来计算的

//结构体的大小是  4 byte * 5 == 20 byte
struct Test
{
 int Num;
 char *pcName;
 short sDate;
 char cha[2];
 short sBa[4];
}*p = (struct Test*)0x100000;
//这里的p是一个结构体指针变量,是可以指向如上这样结构体的一个指针

假设p 的值为0x100000。 如下表表达式的值分别为多少?
已知,结构体Test类型的变量大小是 20 byte

int main()
{
//结构体指针 + 1 --> 跳过整个结构体
 printf("%p\n", p + 0x1);//0x100000 + 0x1 ==> 0x100000 + 20 ==> 0x100000 + 0x14 ==> 0x100014
    
//长整形 + 1 --> 长整形 + 1(记住,这是一个坑,这里的指针p被强制类型转换为了【无符号长整形】的数据,表示的不是指针了)
 printf("%p\n", (unsigned long)p + 0x1);//0x100000 + 0x1 ==> 1,048,576 + 1 ==> 0x100000 + 0x1 ==> 0x100001
    
//整型指针  + 1 --> 跳过一个int类型的大小
 printf("%p\n", (unsigned int*)p + 0x1);//0x100000 + 0x1 ==> 0x100000 + 4 ==> 0x100000 + 0x4 ==> 0x10004
 return 0;
}

打印结果:

0x100014
0x100001
0x10004

③ 题

int main()
{
    int a[4] = { 1, 2, 3, 4 };
    
    //&a + 1 跳过了整个数组,再将【数组地址】强制类型【元素地址】赋给 ptr1,此时ptr指向数组后边
    int *ptr1 = (int *)(&a + 1);
    
    //a是首元素地址,将元素地址强制转换为【int型的数值】,得出int型的数值 + 1,再强制类型转换为 int*
    int *ptr2 = (int *)((int)a + 1);
    
    //ptr[-1]就是从ptr位置往前走了一个位置
    //从原来a数组的后边位置(可以想成a[5])变成了a[4]
    printf( "%x,%x", ptr1[-1], *ptr2);
    return 0;
}

下面进行逐个分析,因为电脑作图不是很方便,所以在纸上写的:

在这里插入图片描述

打印结果:

4,2000000

④ 题

#include <stdio.h>
int main()
{
    
    //在括号中数字用逗号分隔,那么得出的结果为最后一个逗号后边的数
    int a[3][2] = { (0, 1), (2, 3), (4, 5) };
    int *p;
    
    //p指向首元素地址,所以取出来的值为1
    p = a[0];
    printf( "%d", p[0]);//1
 return 0;
}

打印结果:

1

⑤ 题

int main()
{
    int a[5][5];
    int(*p)[4];
    
    //p为数组指针,指向了a的第一行
    p = a;
    printf( "%p,%d\n", &p[4][2] - &a[4][2], &p[4][2] - &a[4][2]);
    return 0;
}

这个就要画图理解了, 其实和第 ③ 题还是蛮像的,下面为手绘的图:

在这里插入图片描述

FFFFFC,-4

⑥ 题

int main()
{
    int aa[2][5] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
    
    //aa第 0 行的地址,&aa表示整个数组的地址
    //+ 1 就是跨过了整个数组,指向了整个数组的后边
    //然后再将二维数组地址类型的地址强制类型转换为一个元素的地址,或者说是一个变量的地址
    //所以ptr1就是指向了aa数组的后边(挨着)
    int *ptr1 = (int *)(&aa + 1);
    
    //aa是第 0 行的地址
    //aa + 1 就是第 1 行的地址
    //*(aa + 1) 就是第 1 行 第 0 个元素的地址
    //ptr2 指向第 1 行 第 0 个元素的地址,也就是&a[1][0]
    int *ptr2 = (int *)(*(aa + 1));
    
    //因为在二维数组中,所有元素的地址都是连续的,所以-1后,打印的元素是都是原本指向位置的前一个
    printf( "%d,%d", *(ptr1 - 1), *(ptr2 - 1));
    return 0;
}

打印结果:

10,5

⑦ 题

#include <stdio.h>
int main()
{
 char *a[] = {"work","at","alibaba"};
 //pa指向a的首元素地址
 char**pa = a;
 //指向下一个元素
 pa++;
 printf("%s\n", *pa);//at
 return 0;
}

打印结果:

at

⑧ 题 - 挺复杂的

int main()
{
 char *c[] = {"ENTER","NEW","POINT","FIRST"};
 char**cp[] = {c+3,c+2,c+1,c};
 char***cpp = cp;
    
//cpp指向的是cp的首地址,即cp[0],也就是元素 c + 3 的位置,而cpp中存的是&cp[0]
//++cpp,指向cp[1],也就是元素 c + 2 的位置,而cpp中存的是&cp[1]
//*++cpp,是解引用&cp[1],得出cp[1]
//**++cpp,接上文,解引用cp[1],即解引用 c + 2,或者说是*(c + 2),得出来的是POINT
 printf("%s\n", **++cpp);//POINT

//如果cpp前面没有另一个变量或者常量或者地址,那么前面这些符号*--*++就没有所谓的计算顺序,优先级也不存在了,此时哪个符号离cpp最近先算哪一个
//++cpp cpp指向了cp[2],此时cpp中存储的是 &cp[2]
//*++cpp 相当于对&cp[2]进行解引用,得出来的是cp[2]
//--*++cpp 相当于是--cp[2],也就是相当于是--(c + 1),这里更改了cp数组中存储的地址,将cp[2]的元素--后,c + 1后,cp[2]就是c
//*--*++cpp 相当于 *c,是字符串"ENTER"中的第 1 个字符'E'的地址,如果打印格式为“ %s ”,得出来的是ENTER
//*--*++cpp 相当于*(c + 3),此时是字符串"ENTER"中的第 2 个字符'E'的地址
 printf("%s\n", *--*++cpp+3);//ER

//在理解次行代码之前,要先知道前面的运算已经
//1. 将cp[2]变成 c
//2. 将cpp指向了cp[2],即cpp存 &cp[2]

//cpp[-2] 相当于*( cpp - 2 ),由上可得,此时 cpp 指向的是cp[2],也就是 cpp 中存储的是 &cp[2],那么cpp - 2指向的就是cp[0],也就是cpp - 2表示的地址实际上是&cp[0],所以*cpp[2]可以相当于是cp[0] --> 得出 *cpp[-1] 就是 c + 3
//*cpp[-2] 此时将cpp[-2]进行解引用,其实就是*( c + 3 ),解引用后指向的就是字符串"FIRST"中的字符'F'
//*cpp[-2] + 3 此时指向了常量字符串"FIRST"中的字符'f'
 printf("%s\n", *cpp[-2]+3);

//在理解次行代码之前,要先知道前面的运算已经
//1. 将cp[2]变成 c
//2. 将cpp指向了cp[2],即cpp存 &cp[2]

//cpp[-1][-1] 意思其实就相当于 *(  *(cpp - 1) - 1  ),实际上就是*(  *( &cp[2] - 1) - 1  ),得出来就是*(  *cp[1] - 1  ) <   ==   > *(   c + 2 - 1   ) < == > * (   c + 1   ) 此时意思就是指向了常量字符串"NEW"的常量'N'
//cpp[-1][-1] + 1 就是 * ( c + 1 ) + 1,就是指向了常量'N'的下一个常量,即指向了'E'
 printf("%s\n", cpp[-1][-1]+1);//EW
 return 0;
}

打印结果:

POINT
ER
ST
EW

原文地址:https://blog.csdn.net/m0_60605989/article/details/142830562

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!