【C语言】进阶指针(三)—>指针与数组笔试真题详解(下)

简介: 【C语言】进阶指针(三)—>指针与数组笔试真题详解(下)

笔试题(2)

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);
     return 0;
}

答案:0x100014 0x100001 0x100004

分析:

p的类型为结构体指针struct Test*,步长为struct Test,0x1是十六进制数字,转为十进制为1,+1后相当于+20(整型),转化为十六进制加到0x100000后即为0x100014。

p被转化为数字,+1就是0x100000+1,为0x100001。

p被转化为unsigned int*类型,步长为4个字节,+1就是跳过4个字节,即0x100000+4=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,2000000

对于ptr1:

&a+1指针指向元素'4'后面的位置,将该指针强制转换为int*类型,ptr1[-1]相当于*(ptr1-1),又因为ptr1的步长为int,所以解引用得到元素为'4',用%x(十六进制打印)得到值为4。

对于ptr2:

涉及到了内存的存储,为了更好地讲解,请看下图:


笔试题(4)

int main()
{
    int a[3][2] = { (0, 1), (2, 3), (4, 5) };
    int* p;
    p = a[0];
    printf("%d", p[0]);
    return 0;
}
//程序输出的结果是什么?

答案:1

这里有一个陷阱,我们知道二维数组的定义方法应为int a[3][2]={{0,1},{2,3},{4,5}};

但是本题为int a[3][2] = { (0, 1), (2, 3), (4, 5) };

他实际上为int a[3][2] = { 1, 3, 5 };

即:

所以值为1。


笔试题(5)

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;
}
//程序的结果是什么?

答案:FFFFFFFC,-4

根据前面学过的知识,我们知道p是数组指针,指向的元素类型为int [4]。

我们将p[4][2]也理解为二维数组,那么&p[4][2]就是指向p数组第5行第三列的元素,即为图中所示。

指针相减得到两个指针之间的元素个数,又因为地址是由低到高变化的,所以小地址减去大地址得到负数,为-4。

%p是打印地址的操作符,又因为-4在内存中存储的是补码:

1111 1111 1111 1111 1111 1111 1111 1100  //-4的补码

  F      F      F      F      F      F      F      C  

转化为16进制数字0xFFFFFFFC


笔试题(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,5

ptr1:

&aa取出的是整个数组的地址,+1指向元素'10'后面的元素,并强制转化为int*类型,打印时-1指向元素'10',解引用得到元素'10',所以值为10。

ptr2:

aa+1指向二维数组的第二行的一维数组,解引用得到该一维数组首元素的地址,也可以将*(aa+1)理解为aa[1],即为6的地址,打印时-1指向元素'5',解引用得到元素'5',所以值为5。

解引用一个数组(非数组名)的地址,得到的是该数组首元素的地址。


笔试题(7)

int main()
{
     char *a[] = {"work","at","alibaba"};
     char**pa = a;
     pa++;
     printf("%s\n", *pa);
     return 0;
}
//程序的结果是什么?

答案:at

a本质上是指针数组,该数组存放着三个字符串首个字符的地址。

pa指向的是数组a的首元素的地址,所以pa是一个二级指针,pa指向指向字符'w'的指针。

即:

所以得到的值为at。


笔试题(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  ER  ST  EW

与第七题同理,难度略高。

如图,当我们知道指针之间的关系后,那么还需要攻克的就是符号优先级的问题。

1、**++cpp,++的优先级高于*,所以cpp先+1在连续两次解引用,得到元素'P'的地址,打印得到POINT。

2、*--*++cpp+3,cpp先++,再解引用,再--,再解引用,最后+3,得到元素'E'的地址,打印得到ER。

3、*cpp[-2]+3,可以理解为**(cpp-2)+3,得到元素'S'的地址,打印得到ST。

4、cpp[-1][-1]+1,可以理解为*(*(cpp-1)-1) +1,得到元素'E'的地址,打印得到EW。


小结:进阶指针的学习到这里就全部结束了,想要学习关于进阶指针的全部知识,欢迎到我的主页查询进阶指针(一)与进阶指针(二),接下来博主会持续更新C语言的更多知识, 关注博主不迷路🔥🔥🔥

目录
相关文章
|
20天前
|
存储 NoSQL 编译器
【C语言】指针的神秘探险:从入门到精通的奇幻之旅 !
指针是一个变量,它存储另一个变量的内存地址。换句话说,指针“指向”存储在内存中的某个数据。
73 3
【C语言】指针的神秘探险:从入门到精通的奇幻之旅 !
|
20天前
|
存储 编译器 C语言
【C语言】指针大小知多少 ?一场探寻C语言深处的冒险 !
在C语言中,指针的大小(即指针变量占用的内存大小)是由计算机的体系结构(例如32位还是64位)和编译器决定的。
44 9
|
20天前
|
安全 程序员 C语言
【C语言】指针的爱恨纠葛:常量指针vs指向常量的指针
在C语言中,“常量指针”和“指向常量的指针”是两个重要的指针概念。它们在控制指针的行为和数据的可修改性方面发挥着关键作用。理解这两个概念有助于编写更安全、有效的代码。本文将深入探讨这两个概念,包括定义、语法、实际应用、复杂示例、最佳实践以及常见问题。
40 7
|
20天前
|
传感器 算法 安全
【C语言】两个数组比较详解
比较两个数组在C语言中有多种实现方法,选择合适的方法取决于具体的应用场景和性能要求。从逐元素比较到使用`memcmp`函数,再到指针优化,每种方法都有其优点和适用范围。在嵌入式系统中,考虑性能和资源限制尤为重要。通过合理选择和优化,可以有效提高程序的运行效率和可靠性。
64 6
|
24天前
|
存储 缓存 算法
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式,强调了合理选择数据结构的重要性,并通过案例分析展示了其在实际项目中的应用,旨在帮助读者提升编程能力。
44 5
|
23天前
|
存储 程序员 编译器
C 语言数组与指针的深度剖析与应用
在C语言中,数组与指针是核心概念,二者既独立又紧密相连。数组是在连续内存中存储相同类型数据的结构,而指针则存储内存地址,二者结合可在数据处理、函数传参等方面发挥巨大作用。掌握它们的特性和关系,对于优化程序性能、灵活处理数据结构至关重要。
|
24天前
|
算法 C语言
C语言中的文件操作技巧,涵盖文件的打开与关闭、读取与写入、文件指针移动及注意事项
本文深入讲解了C语言中的文件操作技巧,涵盖文件的打开与关闭、读取与写入、文件指针移动及注意事项,通过实例演示了文件操作的基本流程,帮助读者掌握这一重要技能,提升程序开发能力。
78 3
|
24天前
|
存储 算法 程序员
C 语言指针详解 —— 内存操控的魔法棒
《C 语言指针详解》深入浅出地讲解了指针的概念、使用方法及其在内存操作中的重要作用,被誉为程序员手中的“内存操控魔法棒”。本书适合C语言初学者及希望深化理解指针机制的开发者阅读。
|
24天前
|
程序员 C语言
C语言中的指针既强大又具挑战性,它像一把钥匙,开启程序世界的隐秘之门
C语言中的指针既强大又具挑战性,它像一把钥匙,开启程序世界的隐秘之门。本文深入探讨了指针的基本概念、声明方式、动态内存分配、函数参数传递、指针运算及与数组和函数的关系,强调了正确使用指针的重要性,并鼓励读者通过实践掌握这一关键技能。
35 1
|
28天前
|
存储 C语言 计算机视觉
在C语言中指针数组和数组指针在动态内存分配中的应用
在C语言中,指针数组和数组指针均可用于动态内存分配。指针数组是数组的每个元素都是指针,可用于指向多个动态分配的内存块;数组指针则指向一个数组,可动态分配和管理大型数据结构。两者结合使用,灵活高效地管理内存。