深入学习指针6:与数组和指针相关的笔试题2(C语言)

目录

二维数组相关指针知识

指针运算笔试题解析 


 

Hello,小伙伴们我又来了,今天我们继续上期的内容继续为大家带来重要的笔试题,如果喜欢作者菌的内容的话就三连打卡上车,好废话不多说,开始我们今天的正题!!

 char *p = "abcdef";
 printf("%d\n", strlen(p));
 printf("%d\n", strlen(p+1));
 printf("%d\n", strlen(*p));
 printf("%d\n", strlen(p[0]));
 printf("%d\n", strlen(&p));
 printf("%d\n", strlen(&p+1));
 printf("%d\n", strlen(&p[0]+1));

我们来看看这样的一组代码。

大家可以试着看看能不能找出答案

我来带大家分析一波:

首先我们能了解到,p指的就是字符串的首地址,同时被 “”包围的字符串会在末尾自动加上‘\0',因此不会出现越界的的问题。

所以 printf("%d\n", strlen(p));

的结果就是6

printf("%d\n", strlen(p+1));

p + 1就相当于指向的字符串的第二个字符的地址,故结果为5

printf("%d\n", strlen(*p));

*p就是字符串的首字符,将首字符串给strlen函数,函数会将a当成地址去访问,而我们目前并没有开辟这样发的空间,所以,没有结果。

printf("%d\n", strlen(p[0]));

这条语句与上一条语句一样都是将字符串给了 strlen函数,p[0]--->*(p + 0)

printf("%d\n", strlen(&p));

&p就代指整个字符串的地址,指向的还是字符串的首元素,故结果还是6

printf("%d\n", strlen(&p+1));

&p + 1就相当于跳过了整个字符串的大小,指向了字符串外,而strlen函数只有在遇到’\0'时才会停下,故返回的是一个随机值

printf("%d\n", strlen(&p[0]+1));

这条语句中的&p[0]指的就是字符串的首元素,他加上1,就代表跳过了一个字符,指向了字符串的第二个元素,故结果为5

二维数组相关指针知识

int a[3][4] = {0};
 printf("%d\n",sizeof(a));
 printf("%d\n",sizeof(a[0][0]));
 printf("%d\n",sizeof(a[0]));
 printf("%d\n",sizeof(a[0]+1));
 printf("%d\n",sizeof(*(a[0]+1)));
 printf("%d\n",sizeof(a+1));
 printf("%d\n",sizeof(*(a+1)));
 printf("%d\n",sizeof(&a[0]+1));
 printf("%d\n",sizeof(*(&a[0]+1)));
 printf("%d\n",sizeof(*a));
 printf("%d\n",sizeof(a[3]));

 数组名的意义:

1. sizeof(数组名),这⾥的数组名表⽰整个数组,计算的是整个数组的⼤⼩。

2. &数组名,这⾥的数组名表⽰整个数组,取出的是整个数组的地址。

3. 除此之外所有的数组名都表⽰⾸元素的地址。

从这里我们可以看出二维数组肯定会比一维数组复杂一点,但也有相似之处,我们可以进一步延伸来推导出我们的答案。

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

在sizeof 这里 a还是指代的整个数组,所以计算的是整个数组的内存空间大小。故答案为 12*4=48

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

a[0][0]就是二维数组中的一个元素,故答案就是4

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

这里就要特别注意了 a[0]指代的就是第一行,第一行的元素有4个  ,所以这条语句的答案就是  16

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

这里a[0] + 1指代的就是二维数组第二行的地址 所以本质上就是计算地址的内存空间的大小,前面说到过,这样的题目就和编译器有关,在VS中,答案就是     4/8

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

这里 *(a[0]+1)指代的就是第一行第二列的元素,等价于 *(a[0] +1)-----> *(&(a+0)+1),就是一个整型元素,内存空间就是4

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

在这里 a + 1指的就是第二行的元素的低地址,所以这里就是计算地址的内存空间地址,所以答案就是  4/8

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

*(a + 1)指代的就是,二维数组的第二行元素,等价于 a[0],所以答案就是第一行元素的内存空间大小  16

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

&a[0]就是第一行元素的地址,所以这里指代的就是第二行元素的地址,所以这里计算出的就是地址在内存空间中的大小,   答案为 4/ 8

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

有了前面的基础,我们也可以很轻易地推出,&a[0] + 1就是第二行元素的地址,解引用就指代的是第二行元素,所以答案就是  4*4 = 16

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

a[3]指代的就是第三行元素,所以这道题就可以很轻易地得出答案,为16

接下来,大家来对一下答案吧!!聪明如你,相信大家都已经理解了二维数组的知识点了吧!!

好,接下来我再来带大家看看几道曾经的指针面试真题!!

指针运算笔试题解析 

题目一:

 #include <stdio.h>
 int main()
 {
     int a[5] = { 1, 2, 3, 4, 5 };
     int *ptr = (int *)(&a + 1);
     printf( "%d,%d", *(a + 1), *(ptr - 1));
     return 0;
 }

这道题怎么来分析呢?其实这道题也并不难。

*(a + 1),我们可以很轻松的推断出,答案为数组的第二个元素 2

ptr怎么来分析呢?

首先我们可以知道,ptr是int*类型的指针,可知在进行加减运算时,会以整形为单位跳过、回缩,

因为ptr指向的位置是:

所以*(ptr - 1)指向的就是5 

 

题目二:

 

//在X86环境下
 
//假设结构体的⼤⼩是20个字节(此处的结构体空间内存大小,在86环境下就是20个字节)
 
//程序输出的结构是啥?
 
struct Test
 {
 int Num;
 char *pcName;
 short sDate;
 char cha[2];
 short sBa[4];
 }*p = (struct Test*)0x100000;

 int main()
 {
 printf("%p\n", p + 0x1);
 printf("%p\n", (unsigned long)p + 0x1);
 printf("%p\n", (unsigned int*)p + 0x1);
 return 0;
 }

这道题,我们因该怎么去分析呢???

首先我要在强调一个概念,只有指针在进行加减运算时,才要注意指针的类型!!

由此我们可以开始推断: 0X1是 16进制数字,就是表示1  此时的p指针是(struct  Test*)类型的,加一就相当于跳过了20个字节,因为 20 转化为16进制数子为 14,所以第一条输出的答案是

0x100014

第二条输出语句 的p是一个无符号长整形数字 所以就相当于只是加上了1,故答案就是 :

0x1000001

第三条输出的 p是(unsigned int*)类型的指针,加上一就相当于跳过了4个字节,所以答案就是:
0下000004

我们就来看看答案吧:

题目三:

 #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;
 }

 这道题看起来很简单是吧,我们可能会习惯性的认为,二维数组的存储情况是这样的:

但如果这样想的话,就恰好中了出题人的圈套,题目中用到的是逗号表达式,所以每一个括号中都只取到左边的数,即真实的存储情况因该是这样的:

所以不难判断出,p 指向的是第一行的元素,所以p[0]就是二位数组第一行元素的第一个元素,即为1

接下来让我们来验证下下答案吧!!

好了,今天的学习就到这里,感谢大家的观看,咱们下期再见,拜拜!! 

  • 37
    点赞
  • 44
    收藏
    觉得还不错? 一键收藏
  • 23
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 23
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值