深入学习指针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));
我们来看看这样的一组代码。
大家index.php/tags-653.html" class="superseo">可以试着看看能不能找出答案
我来带大家分析一波:
首先我们能了解到,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 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 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
接下来让我们来验证下下答案吧!!
好了,今天的学习就到这里,感谢大家的观看,咱们下期再见,拜拜!!