深入理解"指针"之面试题解析

来源:互联网 发布:彩虹秒赞网源码 编辑:程序博客网 时间:2024/06/05 03:21

   该编文章是收集网络上有关指针题目并对其进行整理,其目的是加深对指针的理解,使自己对指针理解更加透彻。文章以讲解题目为主同时在原有题目基础上进行拓展。

   一些理解不正确的地方,希望各位指正! 谢谢

   文章为原创,转载请注明出处,谢谢 ; 

   作者  :  飞哥

1.请说明以下定义指针之间的区别:

char  const * p1;    
char * const  p2;  
char const const p3; 
const char const p4;

  1) p1 称之为: 常量指针,就是指向常量的指针,该指针的目标不可被修改,但是指针本身可以被修改。

   例如:
    int n = 100;
    const int* p = &n; // int const* p;
    *p = 200; // error !
    int m = 1000;
    p = &m;
    (*p)++; // error !


  2) p2 称之为 : 指针常量就是指针类型的常量,该指针本身不能被修改,但是指针的目标可以被修改。

   例如:
    int n = 100;
    int* const p = &n;
    *p = 200; // ok !
    int m = 1000;
    p = &m; // error !
  3)p3和p4指针是意义是相同的,称之为: 常量指针常量,指针本身和它的目标都是常量,都不可被修改。

      这两个指针比较好理解,我再次不再赘述;

   例如: 
    int n = 100, m = 1000;
    const int* const p = &n;
    *p = 200; // error !
    p = &m; // error !

  
   结论:   1.
常量指针,是常量不可以被修改,或者说指向不改变;

              2.指针常量,是指针本身不能被修改;或者说指向可以改变;

   为避免混淆,您可以这样理解:

      口头提问时   :  常量指针和指针常量区别:  "指针"开头表示指针本身不能被修改,"常量"开头表示指向的内容不能被修改;

      自己理解时  :  " * " 后有const表示指针不能被改变; “ * ” 前有const表示指针指向的目标不能被改变;   


2.指针和引用区别

  1)概念不同:
    指针是指向变量的地址;
    引用是为变量起别名。
  2)指针可以为NULL,但引用不能;
     例如:  int *p = NULL;  //ok
               int& p = NULL; //error
  3)指针可以不被初始化,但引用不能;
     例如:  int* p;  //ok
               int& p;  //error;
  4)非常量的指针指向的对象可以改变,但是引用一旦初始化,其引用的对象就不能被改变;
      例如:
        int a,b;
        int* p = &a;
        p = &b;  //此时p指向了b;
      但是:
        int& r = b;
        r = a;  //此时r还是b的别名而不是a的别名;
   5)有指针常量,但是没有引用常量(上诉4已经证明)
       但可以有常量引用:     
       例如:  const int&  r = a;
                 r = 200;  //error;
                 int const & r = a;  //error,无法编译通过,不存在引用常量;
     通过对第一个知识点的理解,相信您能很快理解这个错误原因;
   6)存在指针的指针但不存在引用的引用也不存在引用的指针;
     例如:   char*&  p1 = p;  //ok
                char&*  p1 = p;  //error
    7)存在指针数组但不存在引用数组
     例如:  int * arr[10]; //ok
               int & arr[10]; //error

3.请说明下面输出结果

   
    char str1[] = "abc";  char str2[] = "abc";  const char str3[] = "abc";  const char str4[] = "abc";  const char *str5 = "abc";  const char *str6 = "abc";    char *str7 = "abc";  char *str8 = "abc";   cout << ( str1 == str2 ) << endl;  cout << ( str3 == str4 ) << endl;  cout << ( str5 == str6 ) << endl;  cout << ( str7 == str8 ) << endl;

  
  结果是:0 0 1 1
  str1,str2,str3,str4是数组变量,它们有各自的内存空间;
  而str5,str6,str7,str8是指针,它们指向相同的常量区域。
     如果还是不懂,请看我写的"重新认识数组"这篇文章。

4.下面输出数组大小的函数有没有问题?

int Strlen(char str[]){    return (int)(sizeof(str)-1);}
  有问题,函数 strlen(char str[])与strlen(char* pStr)写法的含义相同,在形参与实参结合过程中,
  实际上是一个赋值的过程,实参为数组传到形参后,形参只是一个指针,指针大小在32位下是4字节;
  所以有问题;
  如果还是不懂,请看我写的"重新认识数组"这篇文章。

5.说说下面两者的区别:

   char *p = “abcdefg”;
   char a[] =“abcdefg”;
   那么,p[i]与a[i]的区别?
  a[i]是直接在(符号表a的地址+i)处获取内容,即为直接引用。
  p[i]是先获取符号表p地址的内容,然后在该内容上+i地址处获取内容,即为间接引用。这里的“间接”指的是要被操作的地址不能直接从编译器符号表     中直接获得,而是从指针对象中获得。

6. 
 int a[5]={1,2,3,4,5}; 
 int *ptr=(int *)(&a+1); 
 printf("%d,%d/n",*(a+1),*(ptr-1));
 输出结果是什么?
 答案: 2,5;  
 释义:  *(a+1)是首地址向后便宜一个4字节取目标,等价于a[1];
           &a  :  此时"a"代表的是整个数组;   //如果不懂,可以 看"重新认识数组"中的如何区分什么时候代表整个数据什么时候代表首地址;
                     等价于 int (*a)[5]的写法(数组指针),即a是指向数组的,
                     而ptr-1则是普通的整形指针向后偏移4字节,
7.说说下面的区别? 
   int (*p[10])(int);
   int  (*p)(int);
   int (* p)[10];
  释义:   int  (*p)(int);  是一个函数指针,指向一个类似 int func(int ) 类型的函数;
             int  (*p[10])(int),是指向10个类似上面的函数指针的指针
             int (*p)[10]; //数组指针,存放指向数组的指针;
8.请问下面代码有什么结果?
void get_memory(char *p){p = (char *)malloc(sizeof(char) * 100);}void test(void){char *str = NULL;get_memory(str);strcpy(str, "hello world");printf("%s\n", str);}

  答案: 段错误
  释义:  char* str = NULL;也就是说str变量没有任何指向;
            当其作为参数传入get_memory后形参作为任然是一个野指针,分配空间后和实任何实参的str没有任何关系;
            实参str仍然为null,拷贝时当然会崩溃或者出现段错误;
  修改:  get_memory(&str);便可;











 


        
   


     








0 0
原创粉丝点击