收集整理的一些面试题

来源:互联网 发布:儿童百科全书推荐 知乎 编辑:程序博客网 时间:2024/04/29 13:08

1free()函数

问:下面的程序会在用户输入'freeze'的时候出问题,而'zebra'则不会,为什么?

  1. #include<stdio.h> 
  2.  
  3. int main(int argc, char *argv[]) 
  4.     char *ptr = (char*)malloc(10); 
  5.  
  6.     if(NULL == ptr) 
  7.     { 
  8.         printf("\n Malloc failed \n"); 
  9.         return -1; 
  10.     } 
  11.     else if(argc == 1) 
  12.     { 
  13.         printf("\n Usage  \n"); 
  14.     } 
  15.     else 
  16.     { 
  17.         memset(ptr, 0, 10); 
  18.  
  19.         strncpy(ptr, argv[1], 9); 
  20.  
  21.         while(*ptr != 'z'
  22.         { 
  23.             if(*ptr == ''
  24.                 break
  25.             else 
  26.                 ptr++; 
  27.         } 
  28.  
  29.         if(*ptr == 'z'
  30.         { 
  31.             printf("\n String contains 'z'\n"); 
  32.             // Do some more processing 
  33.         } 
  34.  
  35.        free(ptr); 
  36.     } 
  37.  
  38.     return 0; 

答:这里的问题在于,代码会(通过增加“ptr”)修改while循环里“ptr”存储的地址。当输入“zebra”时,while循环会在执行前被终止,因此传给free()的变量就是传给malloc()的地址,即最初分配给str的地址。但在“freeze”时,“ptr”存储的地址会在while循环里被修改,因此导致传给free()的地址出错,申请的内存前面一部分就没有释放,因为str++,让释放地址时不是从最初申请的那个地址开始释放的,也就导致了seg-fault或者崩溃。

2.问:修改代码片段(或者只读代码)

问:下面的代码段有错,你能指出来吗?

  1. #include<stdio.h> 
  2.  
  3. int main(void
  4.     char *ptr = "Linux"
  5.     *ptr = 'T'
  6.  
  7.     printf("\n [%s] \n", ptr); 
  8.  
  9.     return 0; 

答:这是因为,通过*ptr = ‘T’,会改变内存中代码段(只读代码)“Linux”的第一个字母。这个操作是无效的,因此会造成seg-fault或者崩溃。

试了一下,确实会出错,但是还是不是很理解,为什么像 *str++=*ptr++这种又是正确的了?

3、输出是什么结果,还有(int&)a   与   (int)&a   有什么区别 

#include <iostream> 
using   namespace   std; 
void   main() 
{ 
float   a   =   1.0f; 
cout   < <   &a   < <   endl; 
cout   < <   (int)&a   < <   endl; 
cout   < <   (int&)a   < <   endl; 
cout   < <   boolalpha   < <   (   (int)a   ==   (int&)a   )   < <   endl;   //   输出什么? 
float   b   =   0.0f; 
cout   < <   (int)b   < <   endl; 
cout   < <   (int&)b   < <   endl; 
cout   < <   boolalpha   < <   (   (int)b   ==   (int&)b   )   < <   endl;   //   输出什么? 
} 

解答:cout < < boolalpha < < ( (int)a == (int&)a ) < < endl; // 输出0;

/*(int&)a:将a的引用强制转换为整型,意思是a所在的内存,本来定义的时候为float类型,并初始为1.0f,但现在我要按int类型解释这段内存。1.0f   在内存中的存储为   0   011   1111   1   000   0000   0000   0000   0000   0000.把他按整型数解释为2^29+2^28+2^27+2^26+2^25+2^24+2^23=1065353216       */ 

    cout < < boolalpha < < ( (int)b == (int&)b ) < < endl; // 输出1;

0.0   在内存中的的存储形式 
0000   0000   0000   0000   0000   0000   0000   0000 

            (int&)a   把a强制转换成整形引用类型 ,

     (int)&a   把a的地址强制转换成整型 。
           那为什么(int)a=1呢,因为这个强制转化不是转化float在内存的存储方式,而是转化的a的值。

 

还要注意的是

用 #include <iostream>

 要加 using namespace std;

用iostream.h下面 ,就不用加 using namespace std;

国际标准化

推荐的是:

 #include <iostream>

using namespace std;

不加.h的是现在C++中规定的标准,目的在于使C++代码用于移植和混合嵌入时不受扩展名.h的限制,避免因为.h而造成的额外的处理和修改
而加.h的是c语言的用法,但是在c++中也支持这种用法,主要是为了向下兼容c 的内容,我们平时尽量不用这种方法 iostream是现在C++中规定的标准,目的在于使C++代码用于移植和混合嵌入时不受扩展名.h的限制,避免因为.h而造成的额外的处理和修改。iostream包含的基本功能和对应的旧头文件相同,但头文件的内容在名字空间std中。(在标准化的过程中,库中有些部分的细节被修改了,所以旧头文件和新头文件中的实体不一定完全对应。) 一般情况下应该用这个头文件,而iostream.h则是老式的,以后有可能被淘汰。 

5、

下列代码的运行结果是什么?

int *ptr;

ptr=(int *)0x8000;

*ptr=3;

解答:指针问题,首先将指针ptr指向一个指定的地址,即对一个未作声明的地址直接进行访问,所以访问出错。这块地址可能已经被用,或者被其他程序占用等,因此会导致错误。

int *ptr;

*ptr=3;

这样也会导致错误,因为ptr没有分配一个合法的地址,在定义的时候,系统随机分配了一个地址给ptr,而这个地址可能是不合法的,已经被占用了的,所以会导致出错,如果 int a;ptr=&a;加这两句就不会出错。

6、

有了malloc/free为什么还要new/delete ?

       malloc与free是C++/C语言的标准库函数,new/delete是C++的运算符。它们都可用于申请动态内存和释放内存。

对于非内部数据类型的对象而言,光用maloc/free无法满足动态对象的要求。对象在创建的同时要自动执行构造函数,对象在消亡之前要自动执行析构函数。由于malloc/free是库函数而不是运算符,不在编译器控制权限之内,不能够把执行构造函数和析构函数的任务强加于malloc/free。

       因此C++语言需要一个能完成动态内存分配和初始化工作的运算符new,以及一个能完成清理与释放内存工作的运算符delete。注意new/delete不是库函数。

我们先看一看malloc/free和new/delete如何实现对象的动态内存管理,见示例7-8。

class Obj

{

public :

        Obj(void){ cout << “Initialization” << endl; }

~Obj(void){ cout << “Destroy” << endl; }

void    Initialize(void){ cout << “Initialization” << endl; }

void    Destroy(void){ cout << “Destroy” << endl; }

};

void UseMallocFree(void)

{

    Obj  *a = (obj *)malloc(sizeof(obj));   // 申请动态内存

    a->Initialize();                        // 初始化

    //…

    a->Destroy();   // 清除工作

    free(a);        // 释放内存

}

void UseNewDelete(void)

{

    Obj  *a = new Obj;  // 申请动态内存并且初始化

    //…

    delete a;           // 清除并且释放内存

}

示例7-8 用malloc/free和new/delete如何实现对象的动态内存管理

 

类Obj的函数Initialize模拟了构造函数的功能,函数Destroy模拟了析构函数的功能。函数UseMallocFree中,由于malloc/free不能执行构造函数与析构函数,必须调用成员函数Initialize和Destroy来完成初始化与清除工作。函数UseNewDelete则简单得多。

所以我们不要企图用malloc/free来完成动态对象的内存管理,应该用new/delete。由于内部数据类型的“对象”没有构造与析构的过程,对它们而言malloc/free和new/delete是等价的。

    既然new/delete的功能完全覆盖了malloc/free,为什么C++不把malloc/free淘汰出局呢?这是因为C++程序经常要调用C函数,而C程序只能用malloc/free管理动态内存。

如果用free释放new创建的动态对象,那么该对象因无法执行析构函数而可能导致程序出错。如果用delete释放malloc申请的动态内存,理论上讲程序不会出错,但是该程序的可读性很差。所以new/delete必须配对使用,malloc/free也一样。



 

原创粉丝点击