指针和数组笔试题解析(下)

简介: 指针和数组笔试题解析(下)

题  五


1. char *p = "abcdef";
2. printf("%d\n", sizeof(p));//  4/8
3. printf("%d\n", sizeof(p + 1));//  4/8
4. printf("%d\n", sizeof(*p));//  1
5. printf("%d\n", sizeof(p[0]));// 1个
6. printf("%d\n", sizeof(&p));// 4/8
7. printf("%d\n", sizeof(&p + 1));// 4/8
8. printf("%d\n", sizeof(&p[0] + 1));//  4/8

解释如下

printf("%d\n", sizeof(p));// 4/8

解释:p是一个指针变量,指针大小为4/8

printf("%d\n", sizeof(p + 1));//  4/8

解释:p+1是'b'的地址,是地址大小就是4/8个字节

printf("%d\n", sizeof(*p));//  1

解释:*p 就是'a',就是1个字节

printf("%d\n", sizeof(p[0]));// 1

解释:p[0]等价 *(p+0)等 价 *p ,所以1个字节

1. printf("%d\n", sizeof(&p));// 4/8
2. printf("%d\n", sizeof(&p + 1));// 4/8
3. printf("%d\n", sizeof(&p[0] + 1));//  4/8

解释:都为地址,所以大小都为4/8个字节


题  六


1. // char* p = "abcdef";
2. // printf("%d\n", strlen(p));//6
3. // printf("%d\n", strlen(p + 1));//5
4. // //printf("%d\n", strlen(*p));//err
5. // //printf("%d\n", strlen(p[0]));//err
6. // printf("%d\n", strlen(&p));//随机值
7. // printf("%d\n", strlen(&p + 1));//随机值
8. // printf("%d\n", strlen(&p[0] + 1));//5

这题我就不详细讲解了,请各位宝子们配合下图与前面所讲自行理解一下吧

二维数组  


1. int a[3][4] = {0};
2. printf("%d\n",sizeof(a));// 48
3. printf("%d\n",sizeof(a[0][0]));// 4
4. printf("%d\n",sizeof(a[0])); // 16
5. printf("%d\n",sizeof(a[0]+1));// 4/8
6. printf("%d\n",sizeof(*(a[0]+1)));// 4
7. printf("%d\n",sizeof(a+1));// 4/8
8. printf("%d\n",sizeof(*(a+1)));// 16
9. printf("%d\n",sizeof(&a[0]+1));// 4/8
10. printf("%d\n",sizeof(*(&a[0]+1)));// 16
11. printf("%d\n",sizeof(*a));// 16
12. printf("%d\n",sizeof(a[3]));// 16

在做题之前,务必知道下图中的知识点

二维数组可以看成存放着一维数组的数组 ,接下来我们看一下题解

printf("%d\n", sizeof(a));// 48

解释:3*4*4 = 48

printf("%d\n", sizeof(a[0][0]));//4

解释:首元素a[0][0]的大小

printf("%d\n", sizeof(a[0]));// 16

解释:a[0]是第一行这个一维数组的数组名,数组名算是单独放在sizeof内部了,计算的是整个数组的大小,大小是16个字节

printf("%d\n", sizeof(a[0] + 1));// 4/8

解释:a[0]作为第一行的数组名,没有单独放在sizeo内部,没有&。a[0]表示数组首元素的地址,也就是a[0][0]的地址。所以a[0]+1是第一行第二个元素的地址,是地址就是4/8个字节

printf("%d\n", sizeof(*(a[0] + 1)));//4

解释:计算的是就是第一行第2个元素的大小

printf("%d\n", sizeof(a + 1));// 4/8

解释:a是数组首元素的地址,是第一行的地址 int(*)[4]。a+1 就是第二行的地址

printf("%d\n", sizeof(*(a + 1)));// 16

解释:*(a+1) --> a[1] -> sizeof(*(a+1))->sizeof(a[1]) 计算的是第二行的大小。a+1 --> 是第二行的地址,int(*)[4]。*(a+1) 访问的第二行的数组

printf("%d\n", sizeof(&a[0] + 1));// 4/8

解释:&a[0]是第一行的地址 int(*)[4],&a[0]+1 是第二行的地址 int(*)[4]

printf("%d\n", sizeof(*(&a[0] + 1)));// 16

解释:计算的是第二行的大小

printf("%d\n", sizeof(*a));// 16

解释:计算的是第一行的大小-16。a是数组首元素的地址,就是第一行的地址。*a 就是第一行,*a 等价于*(a+0) 等价于 a[0]

printf("%d\n", sizeof(a[3]));// 16

解释:a[3]等价于int [4],所以大小为16


指针笔试题


笔试题一


1. int main()
2. {
3.  int a[5] = { 1, 2, 3, 4, 5 };
4.  int *ptr = (int *)(&a + 1);
5.  printf( "%d,%d", *(a + 1), *(ptr - 1));
6. //结果为  2,5
7. return 0;
8. }

解释图如下


笔试题二


1. //这里告知结构体的大小是20个字节
2. struct Test
3. {
4.  int Num;
5.  char *pcName;
6.  short sDate;
7.  char cha[2];
8.  short sBa[4];
9. }*p;
10. //假设p 的值为0x100000。 如下表表达式的值分别为多少?
11. //已知,结构体Test类型的变量大小是20个字节
12. int main()
13. {
14.  printf("%p\n", p + 0x1);
15.  printf("%p\n", (unsigned long)p + 0x1);
16.  printf("%p\n", (unsigned int*)p + 0x1);
17. return 0;
18. }

这里我们注意我们如果要运行这个代码,并得出题中所要求的结果,我们还需要对*p进行改造,如下

1. //struct Test
2. //{
3. // int Num;
4. // char* pcName;
5. // short sDate;
6. // char cha[2];
7. // short sBa[4];
8. //}* p = (struct Test*)0x100000;

这样p就等于0x100000,就可以开始运行测试了,运行结果如下

 

这道题我们来一句一句解读一下

printf("%p\n", p + 0x1);

解释:p为指针变量,加0x1就就是加一,也就是跳过一个结构体(20个字节),所以结果为0x100014

printf("%p\n", (unsigned long)p + 0x1);

解释:这里由于强制类型转换了为unsigned long型,所以这里的加0x1就是加1,所以结果为0x100001

printf("%p\n", (unsigned int*)p + 0x1);

解释:这里由于强制类型转换了为unsigned int*型,这里加一就只跳了一个整型的,所以加4,结果为0x100004


笔试题三


1. int main()
2. {
3.  int a[4] = { 1, 2, 3, 4 };
4.  int *ptr1 = (int *)(&a + 1);
5.  int *ptr2 = (int *)((int)a + 1);
6.  printf( "%x,%x", ptr1[-1], *ptr2);
7. return 0;
8. }

首先我们得明白这个数组在内存中如何存储,如下图所示

 

其次我们得知道&a,&a+1,int(a),int(a)+1,以及ptr[-1]与ptr的位置,如下图

最后我们还得知道需要访问几个字节,因为打印用的%x,所以访问四个字节

所以最后结果为00000004和00000002


笔试题四


1. #include <stdio.h>
2. int main()
3. {
4.  int a[3][2] = { (0, 1), (2, 3), (4, 5) };
5.  int *p;
6.  p = a[0];
7.  printf( "%d", p[0]);
8. return 0;
9. }

这道题,需要我们注意的是,数组中的元素,(0,1)其实表示的是一个元素为1,这是一个逗号表达式,后面就可以依次类推,结果如下图所示

则p[0]就等价于a[0][0],所以结果为1


笔试题五


1. int main()
2. {
3.  int a[5][5];
4.  int(*p)[4];
5.  p = a;
6.  printf( "%p,%d\n", &p[4][2] - &a[4][2], &p[4][2] - &a[4][2]);
7. return 0;
8. }

这里我借一位大牛的图来跟大家讲解一下

则由图所知&p[4][2]-&a[4][2]的大小为-4,如果用%p打印的话,打印的就是-4的补码,转换如下

1. // //10000000000000000000000000000100---原码
2. // //11111111111111111111111111111011---反码
3. // //1111 1111 1111 1111 1111 1111 1111 1100---补码
4. // //F    F    F    F    F    F    F    C

所以结果为


笔试题六


1. int main()
2. {
3.  int aa[2][5] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
4.  int *ptr1 = (int *)(&aa + 1);
5.  int *ptr2 = (int *)(*(aa + 1));
6.  printf( "%d,%d", *(ptr1 - 1), *(ptr2 - 1));
7. return 0;
8. }

这道题配合下图,以及前面所学我就不进行讲解了

结果为10,5


笔试题七


1. #include <stdio.h>
2. int main()
3. {
4. char *a[] = {"work","at","alibaba"};
5. char**pa = a;
6.  pa++;
7. printf("%s\n", *pa);
8. return 0;
9. }

这道题我们得明白,a是一个指针数组,a里面每一个字符串都是一个指针

那么这道题就简单了,

则*pa就就是字符串"work"的地址,所以结果就为work

 

至此,指针进阶部分就讲解完了,有不对或者不懂的地方记得评论去留言或私信博主!!!

博主制作不易,记得三连。以便关注博主后续创作!!!

相关文章
|
10月前
使用指针访问数组元素
【10月更文挑战第30天】使用指针访问数组元素。
126 3
|
6月前
|
存储 监控 算法
关于员工上网监控系统中 PHP 关联数组算法的学术解析
在当代企业管理中,员工上网监控系统是维护信息安全和提升工作效率的关键工具。PHP 中的关联数组凭借其灵活的键值对存储方式,在记录员工网络活动、管理访问规则及分析上网行为等方面发挥重要作用。通过关联数组,系统能高效记录每位员工的上网历史,设定网站访问权限,并统计不同类型的网站访问频率,帮助企业洞察员工上网模式,发现潜在问题并采取相应管理措施,从而保障信息安全和提高工作效率。
91 7
|
9月前
|
存储 程序员 C++
深入解析C++中的函数指针与`typedef`的妙用
本文深入解析了C++中的函数指针及其与`typedef`的结合使用。通过图示和代码示例,详细介绍了函数指针的基本概念、声明和使用方法,并展示了如何利用`typedef`简化复杂的函数指针声明,提升代码的可读性和可维护性。
258 1
|
10月前
|
存储 程序员 编译器
C 语言数组与指针的深度剖析与应用
在C语言中,数组与指针是核心概念,二者既独立又紧密相连。数组是在连续内存中存储相同类型数据的结构,而指针则存储内存地址,二者结合可在数据处理、函数传参等方面发挥巨大作用。掌握它们的特性和关系,对于优化程序性能、灵活处理数据结构至关重要。
|
10月前
|
存储 NoSQL 编译器
C 语言中指针数组与数组指针的辨析与应用
在C语言中,指针数组和数组指针是两个容易混淆但用途不同的概念。指针数组是一个数组,其元素是指针类型;而数组指针是指向数组的指针。两者在声明、使用及内存布局上各有特点,正确理解它们有助于更高效地编程。
|
10月前
|
存储 C语言 计算机视觉
在C语言中指针数组和数组指针在动态内存分配中的应用
在C语言中,指针数组和数组指针均可用于动态内存分配。指针数组是数组的每个元素都是指针,可用于指向多个动态分配的内存块;数组指针则指向一个数组,可动态分配和管理大型数据结构。两者结合使用,灵活高效地管理内存。
|
10月前
|
容器
在使用指针数组进行动态内存分配时,如何避免内存泄漏
在使用指针数组进行动态内存分配时,避免内存泄漏的关键在于确保每个分配的内存块都能被正确释放。具体做法包括:1. 分配后立即检查是否成功;2. 使用完成后及时释放内存;3. 避免重复释放同一内存地址;4. 尽量使用智能指针或容器类管理内存。
|
10月前
|
存储 人工智能 算法
数据结构实验之C 语言的函数数组指针结构体知识
本实验旨在复习C语言中的函数、数组、指针、结构体与共用体等核心概念,并通过具体编程任务加深理解。任务包括输出100以内所有素数、逆序排列一维数组、查找二维数组中的鞍点、利用指针输出二维数组元素,以及使用结构体和共用体处理教师与学生信息。每个任务不仅强化了基本语法的应用,还涉及到了算法逻辑的设计与优化。实验结果显示,学生能够有效掌握并运用这些知识完成指定任务。
200 4
|
10月前
使用指针访问数组元素
【10月更文挑战第31天】使用指针访问数组元素。
118 2
|
10月前
|
算法 索引
单链表题+数组题(快慢指针和左右指针)
单链表题+数组题(快慢指针和左右指针)
104 1

推荐镜像

更多
  • DNS