C语言面试题---指针篇(二)

版本声明:本文转载于公众号TeachPlus

C语言面试题---指针篇(二)

在上一篇中,我们介绍了关于内存分区的划分,那么现在我们就来看一道跟这个相关的面试题:

阅读下面的程序,找出其中的错误,并说明原因。

  1. # include <stdio.h>
  2. int main()
  3. {
  4. char *str = "abcd";
  5. str[2] = "f";
  6. printf("%s\n",str);
  7. return 0;
  8. }

本题解析

答案:该程序会段错误,因为程序中仅仅只定义了一个字符指针,并没有定义字符串,

只是将字符指针指向了“abcd”这个字符串常量了,而字符串常量"abcd"的存储位置是在

内存的数据段(或静态存储区)中的,存储在这个位置的值,是不允许修改的,

因此在程序中使用 str[2] ='f'  试图修改字符串常量的值,就会出现段错误,当然,

我们可能等不到段错误的出现,因为程序在编译阶段就会被报警告了。

相关知识点

静态存储区的作用非常重要,但是对于我们而言最重要的还是栈区和堆区。对于堆区而言,

重要的就是malloc函数和free函数,一起来看一道关于堆区的题目:

阅读下面程序,写出程序的运行结果:

  1. # include <stdio.h>
  2. # include <stdlib.h>
  3. # include <string.h>
  4. void getMemory( char **p , int num)
  5. {
  6. *p = malloc(num);
  7. }
  8. int main()
  9. {
  10. char * str = NULL;
  11. getMemory(&str,100);
  12. strcpy(str,"hello");
  13. free(str);
  14. if(str != NULL)
  15. {
  16. printf("%p\n",str);
  17. }
  18. return 0;
  19. }

程序运行的结果输出的是指针对象str的值。

在给指针分配内存的时候,其实给指针对象赋了了一个值,这个值就是这片空间的首地址。

随后进行了free操作,free 只是释放的str指向的内存空间,它本身的值还是存在的.

因为内存空间已经被释放了,所以这个指针对象的值,其实是指向没有被分配空间的地址,

如果输出语句之前还存在分配空间的操作的话,这段存储空间是可能被重新分配给其他变量的,


访问这样的越界空间,编译是没有问题的,但是运行时会出现“Segmentation fault”.


所以free之后,有一个好的习惯就是将str=NULL.


不过在该程序中,如果输出str的值,通常还是会打印出hello来。


这是因为,进程中的内存管理理一般不是由操作系统完成的,而是由库函数自己完成的。


当你malloc一块内存的时候,管理库向操作系统申请一块空间(可能会比你申请的大一些),

然后在这块空间中记录一些管理信息(一般是在你申请的内存 前面一点),并将可用

内存的地址返回。但是释放内存的时候,管理库通常都不会将内存还给操作系统,

也可以理解成为不会立即清除内存空间中的内容的,因此你是可以继续访问这块地址的。
C语言面试题---指针篇(二)