• 面试题集锦


    2.引用与指针有什么区别? 

    • 引用必须被初始化,指针不必。 
    • 引用初始化以后不能被改变,指针可以改变所指的对象。
    • 不存在指向空值的引用,但是存在指向空值的指针。

    6.堆栈溢出一般是由什么原因导致的?      

      没有回收垃圾资源。

    7.什么函数不能声明为虚函数? 
          构造函数不能声明为虚函数。

    9.写出float x 与“零值”比较的if语句。      

      if(x>0.000001&&x<-0.000001)

    12.IP地址的编码分为哪俩部分? 
         IP地址由两部分组成,网络号和主机号。不过是要和“子网掩码”按位与上之后才能区分哪些是网络位哪些是主机位。

    11.对于一个频繁使用的短小函数,在C语言中应用什么实现,在C++中应用什么实现?    

      c用宏定义,c++用inline 

    17

    unsigned char *p1; 

    unsigned long *p2; 
    p1=(unsigned char *)0x801000;  

    p2=(unsigned long *)0x810000; 

    请问p1+5=   p2+5=   
    答案:0x801005(相当于加上5位) 0x810020(相当于加上20位);

    int *p1=(int*)0x00801000;
    int *p2=(int*)0x00801004;

    unsigned char *p3=(unsigned char *)0x00801000;
    unsigned char *p4=(unsigned char *)0x00801004;

    printf("%d ",p2-p1);//1
    printf("%d ",p4-p3);//4

    -----------------------------------------------------------------------------------

    1. 用宏定义写出swap(x,y)

    答#define swap(x, y) x = x + y; y = x - y; x = x - y;

    2. 一语句实现x是否为2的若干次幂的判断 答:方法1)int i = 512; 
    cout << boolalpha << ((i & (i - 1)) ? false : true) << endl; //位与为0,则表示是2的若干次幂

    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. 以下代码中的两个sizeof用法有问题吗?[C易] 
    void UpperCase( char str[] ) // 将 str 中的小写字母转换成大写字母 


      for( size_t i=0; i<sizeof(str)/sizeof(str[0]); ++i ) 

      {  

        if( 'a'<=str[i] && str[i]<='z' ) 

          str[i] -= ('a'-'A' ); 

      }

    char str[] = "aBcDe"; 
    cout << "str字符长度为: " << sizeof(str)/sizeof(str[0]) << endl; 

    UpperCase( str ); 

    cout << str << endl; 
    答:函数内的sizeof有问题。根据语法,sizeof如用于数组,只能测出静态数组的大小,无法检测动态分配的或外部数组大小。

      函数外的str是一个静态定义的数组,因此其大小为6,函数内的str实际只是一个指向字符串的指针,没有任何额外的与数组相关的信息,因此sizeof作用于上只将其当指针看,一个指针为4个字节,因此返回4。    

    注意:数组名作为函数参数时,退化为指针. 
            数组名作为sizeof()参数时,数组名不退化,因为sizeof不是函数. 

    5. 指出下面代码的输出,并解释为什么。(不错,对地址掌握的深入挖潜) 

    main() 


      int a[5]={1,2,3,4,5}; 

      int *ptr=(int *)(&a+1); 

      printf("%d,%d",*(a+1),*(ptr-1)); 


    输出:2,5 
    *(a+1)就是a[1],*(ptr-1)就是a[4],执行结果是2,5 
    &a+1不是首地址+1,系统会认为加一个a数组的偏移,是偏移了一个数组的大小(本例是5个int) 
    int *ptr=(int *)(&a+1);  
    则ptr实际是&(a[5]),也就是a+5 原因如下:

    &a是数组指针,其类型为 int (*)[5]; 
    而指针加1要根据指针类型加上一定的值, 不同类型的指针+1之后增加的大小不同 
    a是长度为5的int数组指针,所以要加 5*sizeof(int) 所以ptr实际是a[5] 
    但是prt与(&a+1)类型是不一样的(这点很重要) 所以prt-1只会减去sizeof(int*) 
    a,&a的地址是一样的,但意思不一样,a是数组首地址,也就是a[0]的地址,&a是对象(数组)首地址,a+1是数组下一元素的地址,即a[1],&a+1是下一个对象的地址,即a[5]. 

    6.关键字volatile有什么含意?并举出三个不同的例子.

    它是被设计用来修饰被不同线程访问和修改的变量

    作为指令关键字,确保本条指令不会因编译器的优化而省略,且要求每次直接读值.

    一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。
    精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。下面是volatile变量的几个例子:
    1). 并行设备的硬件寄存器(如:状态寄存器)
    2). 一个中断服务子程序中会访问到的非自动变量(Non-automatic variables)
    3). 多线程应用中被几个任务共享的变量
     
    7.int (*p)[n];------p为指向一维数组的指针,这个一维数组有n个整型数据。
     

    3. 数组越界问题 (这个题目还是有点小险的) 下面这个程序执行后会有什么错误或者效果: 

    #define MAX 255 

    int main() 


      unsigned char A[MAX],i; 

      for (i=0;i<=MAX;i++) 

        A[i]=i; 


    解答:MAX=255,数组A的下标范围为:0..MAX-1,这是其一,

    其二 当i循环到255时,循环内执行: A[255]=255;这句本身没有问题,但是返回for (i=0;i<=MAX;i++)语句时,由于unsigned char的取值范围在(0..255),i++以后i又为0了..无限循环下去. 
    注:char类型为一个字节,取值范围是[-128,127],unsigned char [0 ,255]

    4.restrict是c99标准引入的,它只可以用于限定和约束指针,并表明指针是访问一个数据对象的唯一且初始的方式.即它告诉编译器,所有修改该指针所指向内存中内容的操作都必须通过该指针来修改,而不能通过其它途径(其它变量或指针)来修改;这样做的好处是,能帮助编译器进行更好的优化代码,生成更有效率的汇编代码.如 int *restrict ptr, ptr 指向的内存单元只能被 ptr 访问到,任何同样指向这个内存单元的其他指针都是未定义的,直白点就是无效指针。

    5.析构函数也是特殊的类成员函数,它没有返回类型,没有参数,不能随意调用,也没有重载。只是在类对象生命期结束的时候,由系统自动调用释放在构造函数中分配的资源。

     

    //为了实现链式操作,将目的地址返回,加3分!

    char * strcpy( char *strDest, const char *strSrc ) 

      assert( (strDest != NULL) && (strSrc != NULL) ); 

      char *address = strDest; 

      while( (*strDest++ = * strSrc++) != '’ ); 

      return address; 

    }

    (2)数组名可以转换为指向其指代实体的指针,而且是一个指针常量,不能作自增、自减等操作,不能被修改; 
    char str[10];  
    str++; //编译出错,提示str不是左值

    (3)数组名作为函数形参时,沦为普通指针。

    试题3:写一个“标准”宏MIN,这个宏输入两个参数并返回较小的一个。另外,当你写下面的代码时会发生什么事? 
    least = MIN(*p++, b);  
     解答: 
    #define MIN(A,B) ((A) <= (B) ? (A) : (B))

    MIN(*p++, b)会产生宏的副作用

    宏定义#define MIN(A,B) ((A) <= (B) ? (A) : (B))对MIN(*p++, b)的作用结果是: ((*p++) <= (b) ? (*p++) : (b)) 

    ++被执行两次

    试题4:为什么标准头文件都有类似以下的结构?  
    #ifndef __INCvxWorksh 

    #define __INCvxWorksh  

    #ifdef __cplusplus  
    extern "C" 

    #endif  

    /*...*/  
    #ifdef __cplusplus 

    }  
    #endif  
    #endif /* __INCvxWorksh */ 

    该函数被C编译器编译后在symbol库中的名字为_foo,而C++编译器则会产生像_foo_int_int之类的名字。_foo_int_int这样的名字包含了函数名和函数参数数量及类型信息,C++就是考这种机制来实现函数重载的。   为了实现C和C++的混合编程,C++提供了C连接交换指定符号extern "C"来解决名字匹配问题,函数声明前加上extern "C"后,则编译器就会按照C语言的方式将该函数编译为_foo,这样C++中就可以调用C语言的函数了。

    试题5:编写一个函数,作用是把一个char组成的字符串循环右移n个。比如原来是“abcdefghi”如果n=2,移位后应该是“hiabcdefgh” 

    void func(char sz[],int step)
    {
      int n=strlen(sz);
      char *temp = new char[n+1];
      for(int i=0;i<n;i++)
      {
        temp[(i+step)%n]=sz[i];
      }
      temp[n]='';
      strcpy(sz,temp);
    }

    试题7:编写类String的构造函数、析构函数和赋值函数,已知类String的原型为: 
    class String {  
    public:  
      String(const char *str = NULL); // 普通构造函数    

      String(const String &other); // 拷贝构造函数    

      ~ String(void); // 析构函数  
      String & operate =(const String &other); // 赋值函数   

    private:  
      char *m_data; // 用于保存字符串  

    };  
    解答: 
    //普通构造函数

    String::String(const char *str)  { 
      if(str==NULL)   { 
        m_data = new char[1]; // 得分点:对空字符串自动申请存放结束标志''的空   

        //加分点:对m_data加NULL 判断   

        *m_data = '';   

      }  

      else  { 

        int length = strlen(str);  
        m_data = new char[length+1]; // 若能加 NULL 判断则更好    

        strcpy(m_data, str);   

      } 

    }  
    // String的析构函数  
    String::~String(void)  


       delete [] m_data;

    }  
    //拷贝构造函数  
    String::String(const String &other)    // 得分点:输入参数为const型 

    {  
       int length = strlen(other.m_data);  
       m_data = new char[length+1];     //加分点:对m_data加NULL 判断  

      strcpy(m_data, other.m_data);  

    }  
    //赋值函数  
    String & String::operate =(const String &other) // 得分点:输入参数为const型 

    {  
      if(this == &other)   //得分点:检查自赋值   

        return *this;  
      delete [] m_data;     //得分点:释放原有的内存资源  

      int length = strlen( other.m_data );  
      m_data = new char[length+1];  //加分点:对m_data加NULL 判断  

      strcpy( m_data, other.m_data );  
      return *this;         //得分点:返回本对象的引用 

    试题1:请写一个C函数,若处理器是Big_endian的,则返回0;若是Little_endian的,则返回1   

    解答: 
    int checkCPU() 

    {  

      union w   {  
        int a;    

        char b[sizeof(int)];   

      } c;   

      c.a = 1; 

      return (c.b[0] == 1);  

    }  

    试题:逐层打印二叉树节点值

    分析 采用宽度优先搜索

    void LinePrint(Tree *T)
    {
      deque<Node*>Que;
      Que.push_back(T->root);
      while(!Que.empty())
      {
        Node *p = Que.front();
        Que.pop_front();
        printf("%d ",p->key);
        if(p->left != NIL)
        {
          Que.push_back(p->left);
        }
        if(p->right != NIL)
        {
          Que.push_back(p->right);
        }

      }
    }

  • 相关阅读:
    一种开源的分布式消息系统Nats
    资产盘点:除了金钱,一个人还有哪些资产?
    博客首页规则改版公告
    <html>
    欢迎使用CSDN-markdown编辑器
    java 小程序查看器 启动:未初始化小程序 解决方法
    Hadoop2.6.0版本号MapReudce演示样例之WordCount(一)
    深入学习IOZone【转】
    i.MX6UL -- PWM用户空间使用方法【转】
    linux PWM蜂鸣器移植以及驱动程序分析【转】
  • 原文地址:https://www.cnblogs.com/johnsblog/p/3890692.html
Copyright © 2020-2023  润新知