飞道的博客

C语言——指针面试题详解

335人阅读  评论(0)
🐒个人主页:平凡的小苏
📚学习格言:别人可以拷贝我的模式,但不能拷贝我不断往前的激情

目录

 1. 指针和数组笔试题解析

 一维数组

字符数组

二维数组

2. 指针笔试题

笔试题1:

笔试题2:

笔试题3

 笔试题4

 笔试题5

笔试题6  

笔试题7

笔试题8


 1. 指针和数组笔试题解析

数组名的意义:

1. sizeof(数组名),这里的数组名表示整个数组,计算的是整个数组的大小。

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

3. 除此之外所有的数组名都表示首元素的地址

 一维数组


  
  1. int a[] = { 1, 2, 3, 4};
  2. printf( "%d\n",sizeof(a));
  3. //这里数组名单独放在sizeof内部,计算整个数组的大小,结果为 16
  4. printf( "%d\n",sizeof(a+ 0));
  5. //这里数组名没有单独放在sizeof内部,是数组首元素的地址,结果为 4/ 8
  6. printf( "%d\n",sizeof(*a));
  7. //这里数组首元素的地址解引用,计算的是元素大小,结果为 4
  8. printf( "%d\n",sizeof(a+ 1));
  9. //这里数组首元素地址加 1,也是地址,是地址结果就是 4/ 8
  10. printf( "%d\n",sizeof(a[ 1]));
  11. //这里计算元素大小,结果为 4
  12. printf( "%d\n",sizeof(&a));
  13. //取出整个数组的地址,是地址结果就为 4/ 8
  14. printf( "%d\n",sizeof(*&a));
  15. //取出数组的地址,然后解引用,本质是数组名单独放在sizeof内部,结果为 16
  16. printf( "%d\n",sizeof(&a+ 1));
  17. //地址加 1,是地址结果就为 4/ 8
  18. printf( "%d\n",sizeof(&a[ 0]));
  19. //取出首元素的地址,是地址结果就为 4/ 8
  20. printf( "%d\n",sizeof(&a[ 0]+ 1));
  21. //结果为 4/ 8

字符数组


  
  1. char arr[] = { 'a', 'b', 'c', 'd', 'e', 'f'};
  2. printf( "%d\n", sizeof(arr));
  3. //数组名单独,结果为 6,因为sizeof计算的是占用内存的大小,不用找\ 0,并且看类型
  4. printf( "%d\n", sizeof(arr+ 0));
  5. //数组首元素的地址,是地址结果就为 4/ 8
  6. printf( "%d\n", sizeof(*arr));
  7. //数组首元素地址解引用,计算元素大小,结果为 1
  8. printf( "%d\n", sizeof(arr[ 1]));
  9. //结果为 1
  10. printf( "%d\n", sizeof(&arr));
  11. //取地址,是地址结果就为 4/ 8
  12. printf( "%d\n", sizeof(&arr+ 1));
  13. //是地址结果为 4/ 8
  14. printf( "%d\n", sizeof(&arr[ 0]+ 1));
  15. //取出首元素地址加 1,跳过四个字节,是地址结果为 4/ 8
  16. printf( "%d\n", strlen(arr));
  17. //strlen是遇到 '\0'停止,这个不知道什么时候遇到 '\0',所以结果为随机值
  18. printf( "%d\n", strlen(arr+ 0));
  19. //同上为随机值
  20. printf( "%d\n", strlen(*arr));
  21. //对arr解引用拿到第一个字符,转为十进制为 97,strlen是用地址一个一个访问的,所以这个代码error
  22. printf( "%d\n", strlen(arr[ 1]));
  23. //同上error
  24. printf( "%d\n", strlen(&arr));
  25. //随机值
  26. printf( "%d\n", strlen(&arr+ 1));
  27. //随机值
  28. printf( "%d\n", strlen(&arr[ 0]+ 1));
  29. //随机值

  
  1. char arr[] = "abcdef";
  2. //“abcdef\ 0”数组长度为 7
  3. printf( "%d\n", sizeof(arr));
  4. //计算整个数组大小,结果为 7
  5. printf( "%d\n", sizeof(arr+ 0));
  6. 数组首元素的地址,是地址就为 4/ 8
  7. printf( "%d\n", sizeof(*arr));
  8. //计算数组元素的大小,结果为 1
  9. printf( "%d\n", sizeof(arr[ 1]));
  10. //同上,结果为 1
  11. printf( "%d\n", sizeof(&arr));
  12. //取出整个数组的地址,是地址,结果就为 4/ 8
  13. printf( "%d\n", sizeof(&arr+ 1));
  14. //取出数组的地址加 1,跳过数组,指向数组后边,但也是地址,是地址结果就为 4/ 8
  15. printf( "%d\n", sizeof(&arr[ 0]+ 1));
  16. //是地址结果就为 4/ 8
  17. printf( "%d\n", strlen(arr));
  18. //strlen遇到斜杠 0就停止,结果为 6
  19. printf( "%d\n", strlen(arr+ 0));
  20. //同上,结果为 6
  21. printf( "%d\n", strlen(*arr));
  22. //解引用拿到的是字符a,代码错误
  23. printf( "%d\n", strlen(arr[ 1]));
  24. //同上,代码错误
  25. printf( "%d\n", strlen(&arr));
  26. //取出数组的地址,但是数组地址开始也是指向首元素的地址,所以结果为 6
  27. printf( "%d\n", strlen(&arr+ 1));
  28. //取出数组的地址加 1,跳过整个数组,然后不知道什么时候遇到斜杠 0,所以为随机值
  29. printf( "%d\n", strlen(&arr[ 0]+ 1));
  30. //取出数组首元素地址加 1,跳过一个字节,结果为 5

  
  1. char *p = "abcdef";
  2. printf( "%d\n", sizeof(p));
  3. //该指针变量存放的是该字符串首字符的地址,是地址结果就为 4/ 8
  4. printf( "%d\n", sizeof(p+ 1));
  5. //是地址结果就为 4/ 8
  6. printf( "%d\n", sizeof(*p));
  7. //对指针p解引用,计算的是该字符元素的大小,结果为 1
  8. printf( "%d\n", sizeof(p[ 0]));
  9. //同上,结果为 1
  10. printf( "%d\n", sizeof(&p));
  11. //是地址,结果就为 4/ 8
  12. printf( "%d\n", sizeof(&p+ 1));
  13. //是地址,结果就为 4/ 8
  14. printf( "%d\n", sizeof(&p[ 0]+ 1));
  15. 同上,结果为 4/ 8
  16. printf( "%d\n", strlen(p));
  17. //strlen遇到 '\0'就停止,结果为 6
  18. printf( "%d\n", strlen(p+ 1));
  19. //p+ 1跳过一个字节,结果为 5
  20. printf( "%d\n", strlen(*p));
  21. //拿到的是字符a,转为ascii吗为 97,该代码错误
  22. printf( "%d\n", strlen(p[ 0]));
  23. //同上,该代码错误
  24. printf( "%d\n", strlen(&p));
  25. //取p的地址,不知道什么时候遇到斜杠 0,所以为随机值
  26. printf( "%d\n", strlen(&p+ 1));
  27. 同上,结果为随机值
  28. printf( "%d\n", strlen(&p[ 0]+ 1));
  29. 取首字符的地址+ 1跳过一个字节,计算的结果为 5

二维数组


  
  1. int a[ 3][ 4] = {0};
  2. printf( "%d\n",sizeof(a));
  3. //结果为 483* 4* 4= 48
  4. printf( "%d\n",sizeof(a[ 0][ 0]));
  5. //计算元素的大小结果为 4
  6. printf( "%d\n",sizeof(a[ 0]));
  7. //a[ 0]是第一行一维数组的数组名,数组名单独放在sizeof内部,计算的是第一行数组的大小,结果为 16
  8. printf( "%d\n",sizeof(a[ 0]+ 1));
  9. //没有单独放在sizeof内部,是数组的首元素,+ 1跳过四个字节,指向第一行第二列的地址,是地址就为 4/ 8
  10. printf( "%d\n",sizeof(*(a[ 0]+ 1)));
  11. //计算的是元素的大小结果为 4
  12. printf( "%d\n",sizeof(a+ 1));
  13. //a没有单独放在sizeof内部,是首元素的地址,是第一行的地址,+ 1指向第二行的地址,是地址就为 4/ 8
  14. printf( "%d\n",sizeof(*(a+ 1)));
  15. a没有单独放在sizeof内部,是首元素的地址,是第一行的地址,+ 1指向第二行的地址,进行解引用得到第二行的数组名,计算的是第二行数组的大小结果为 16
  16. printf( "%d\n",sizeof(&a[ 0]+ 1));
  17. 取出第一行的地址,再+ 1指向第二行的地址,是地址就为 4/ 8
  18. printf( "%d\n",sizeof(*(&a[ 0]+ 1)));
  19. 取出第一行的地址,再+ 1指向第二行的地址,再进行解引用,得到第二行的数组名,计算的是第二行数组的大小,结果为 16
  20. printf( "%d\n",sizeof(*a));
  21. a是二维数组的数组名,没有单独放sizeof内部,是一维数组第一行的地址,然后进行解引用,得到第一行的数组名,计算的是第一行数组的大小,结果为 16
  22. printf( "%d\n",sizeof(a[ 3]));
  23. //第四行的数组名,虽然越界了但是知道了列,就知道一行有多少个元素,因为sizeof是看类型计算的大小,sizeof再编译阶段就完成了计算,越界不影响,所以结果为 16

2. 指针笔试题

笔试题1


   
  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.     return 0;
  7. }
  8. //程序的结果是什么?
  9. 2 5
  10. 解释: 1.a是数组名,为数组首元素的地址,加 1跳过 4个字节,在进行解引用就得到了 2
  11. 2.取出数组的地址再进行+ 1,跳过整个数组,因为取出数组的地址是数组指针类型,想要放在ptr里面,就需要强制类型转换。ptr- 1往回跳一个字节再进行解引用得到的结果为 5.

笔试题2:


    
  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. }
  19. 结果为: 001000140010000100100004
  20. 解释: 1.因为结构体的大小为 20个字节,指针p+ 1跳过 20个字节所以结果为 00100014
  21. 2.先将p强制类型转换为无符号整型,整型+ 1就跳过一个字节,所以地址为 00100001
  22. 3.将p强制类型转换为无符号整型指针,无符号整型指针+ 1就跳过四个字节,所以地址为 00100004

笔试题3


    
  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. }
  9. 结果为: 42000000

解释如图所示:

 笔试题4
 


    
  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. }
  10. 结果为: 1
  11. 解释:因为该数组里面的括号为逗号表达式,所以数组的元素为 1 3 5 0 0 0
  12. p[ 0]访问的是a[ 0][ 0]所以打印出来的是 1

 笔试题5


    
  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. }

    
  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. }

 

 解释:&p[4][2]-&a[4][2]两个指针相减得到的是-4,又因为-4放入内存是补码

则-4的补码为:11111111111111111111111111111100,所以它的地址为fffffc。用%p打印出来就是fffffc

而用%d打印就是-4.

笔试题6  


  
  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. }
  9. 结果为: 10 5
  10. 解释: 1.取出二维数组的地址+ 1,跳过整个二维数组,强制类型转换为 int*,放入ptr1,然后ptr- 1再进行解引用得到的就是 10
  11. 2.aa是数组名,是一维数组的数组名,是第一行数组的地址,aa+ 1跳过一行得到第二行的地址解引用,强制类型转换为 int*放入ptr2,ptr2- 1再进行解引用打印出来的就是 5

笔试题7


  
  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. }
  10. 结果为:at
  11. 解释:a数组每个元素的类型为 char*,所以需要二级指针来接收数组a的地址,然后pa++,跳过一个字节,所以pa指向了a首字符的地址,再对pa进行解引用找到了字符a利用%s打印出来就是at

笔试题8


  
  1. int main()
  2. {
  3. char *c[] = { "ENTER", "NEW", "POINT", "FIRST"};
  4. char**cp[] = {c+ 3,c+ 2,c+ 1,c};
  5. char***cpp = cp;
  6. printf( "%s\n", **++cpp);
  7. printf( "%s\n", *--*++cpp+ 3);
  8. printf( "%s\n", *cpp[- 2]+ 3);
  9. printf( "%s\n", cpp[- 1][- 1]+ 1);
  10. return 0;
  11. }
  12. 结果为:POINT ,ER, ST, EW

解释:cpp存放的是cp首元素的地址,cp 存放的是c的地址

1.由操作符优先级可知,先进行++cpp,所以cpp指向了c+2,然后对cpp第一次解引用得到了c+2的地址,再进行解引用找到了POINT首字符的地址,所以打印出来的是POINT

2.由于cpp已经指向了c+2,所在进行++cpp,就又指向了c+1,对他进行解引用找到了c+1的地址再进行--,所以c+1变为了(c+1-1)得到c,再进行解引用找到了ENTER首字符的地址,再进行+3,跳过三个字节,所以打印出来的是ER

3.由于cpp已经指向了c+1,而那个c+1地址又已经变为了c的地址,所以cpp[-2]本质为*(cpp-2)找到了c+3的地址再进行解引用得到了FIRST首字符的地址,再进行+3跳过了三个字节,所以打印出来的是ST

4.由于cpp已经指向了c+1,而那个c+1地址又已经变为了c的地址,所以cpp[-1][-1]本质为

*(*(cpp-1)-1)找到了NEW首字符的地址,再进行+1跳过一个字节,所以打印出EW

小编的分享到这里就结束了!如果有什么不足的地方,请大佬们指点,小编一定吸取教训,将文章质量提高!!! 


转载:https://blog.csdn.net/VHhhbb/article/details/128643210
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场