c/c++面试题汇总(1)

1.c/c++面试题汇总

#include "stdafx.h"

#include <stdio.h>
#include "string.h"


int _tmain(int argc, _TCHAR* argv[])
{
char string[10],str1[10];
int i;
for (i = 0; i < 10; i++)
{
str1= 'a';
}
strcpy(string,str1);
return 0;

}第一处错误,str1 = 'a';不能将char赋值给char[10],应为str1[i]='a',另外strcpy无结束符,即‘/0’,另外加入后大小为11。

2.

void test3(char* str1)
{
 char string[10];
 if( strlen( str1 ) <= 10 )
 {
  strcpy( string, str1 );
 }
}因为strlen返回值不包括结束符'/0',所以if语句应为if (strlen(str1) < 10 )。

试题3:

void GetMemory(char *p)

{

 p = (char*)malloc(100);

}

 

void Test( void ) 

{

 char *str = NULL;

 GetMemory(str);

 strcpy( str, "hello world" );

 printf( str );

   free(str);

   str=NULL;

}

 

答:对于C语言中的值传递,str传给GetMemory中的形参p后,p的改变不会传递给str(注意:此处说的是p的改变而不是,p指向的

数据的改变),所以str仍然为NULL,会segment fault。

 

试题4:

char *GetMemory(void)

 char p[] = "hello world"; 

 return p; 

}

 

void Test( void )

 char *str = NULL; 

 str = GetMemory(); 

 printf(str);

   free(str);

   str=NULL;

}

答:p是局部变量,位于栈空间,当离开GetMemory,p被销毁。printf(str)打印结果不确定,free那句错误,不是堆空间。

 

试题5:

void GetMemory( char **p, int num )

{

    *p = (char *) malloc( num );

}

 

void Test( void )

{

 char *str = NULL;

 GetMemory( &str, 100 );

 strcpy( str, "hello" ); 

 printf( str ); 

   free(str);

   str=NULL;

}

答:malloc后,应判断 *p是否NULL

 

试题6:

void Test( void )

{

 char *str = (char *)malloc(100);

   strcpy( str, "hello" );

 free( str );

   str = NULL; 

}

答:malloc后,应判断 *p是否NULL

试题7:

swap( int* p1,int* p2 )

{

  int *p;// p未非配空间,这个才是野指针,因为马上使用了

 *p = *p1;

 *p1 = *p2;

 *p2 = *p;

}可以定义成 int p则是正确的

 

还有一个:

 void test(void)
 {
     char str = (char ) malloc(100) 
     strcpy(str, "hello"); 
     free(str);
     if(str != null)
     {
       strcpy(str  “world”);//野指针
       printf(str) 
     }
 }
 请问运行test函数会有什么样的结果?
 篡改动态内存区的内容,后果难以预料,非常危险。
 因为free(str) 之后,str成为野指针,
 if(str != null)语句不起作用。

试题8:写出strcpy和strlen

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

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

 char *address = strDest;   
  while( (*strDest++ = * strSrc++) != ‘\0’ );  
  return address; 


int strlen( const char *str )    //输入参数const 


     assert( strt != NULL );    //断言字符串地址非0      

    int len;

   while( (*str++) != '\0' )       {   
            len++;       }  
     return len;

}

试题9:分别写出BOOL、int、float、指针变量与零值比较的if语句,假设变量名为var

BOOL型变量:if(!var)                    int型变量:if(var==())                  

float型变量:const float A = 0.00001;   if((var>=-A)&& (var <= A))              指针变量if(NULL == var)

试题10:

以下为Windows NT下的32位C++程序,请计算sizeof的值  
void Func ( char str[100] )

 { 
     sizeof( str ) = ? 

}  
void *p = malloc( 100 ); sizeof ( p ) = ?  
解答:  
sizeof( str ) = 4  
sizeof ( p ) = 4  
剖析:Func ( char str[100] )函数中数组名作为函数形参时,在函数体内,数组名失去了本身的内涵,仅仅只是一个指针;在失去其内涵的同时,它还失去了其常量特性,可以作自增、自减等操作,可以被修改。

数组名的本质如下:  
(1)数组名指代一种数据结构,这种数据结构就是数组; 例如: char str[10]; 
cout << sizeof(str) << endl;  
   输出结果为10,str指代数据结构char[10]。  
(2)数组名可以转换为指向其指代实体的指针,而且是一个指针常量,不能作自增、自减等操作,不能被修改; char str[10];  
str++;   //编译出错,提示str不是左值 

(3)数组名作为函数形参时,沦为普通指针。  
Windows NT 32位平台下,指针的长度(占用内存的大小)为4字节,故sizeof( str ) 、 sizeof ( p ) 都为4。

试题10:写一个“标准”宏MIN,这个宏输入两个参数并返回较小的一个。另外,当你写下面的代码时会发生什么事?  
least = MIN(*p++, b);  
解答:  
#define MIN(A,B)    ((A) <=  (B) ? (A) : (B))  
MIN(*p++, b)会产生宏的副作用  
剖析:  
这个面试题主要考查面试者对宏定义的使用,宏定义可以实现类似于函数的功能,但是它终归不是函数,而宏定义中括弧中的“参数”也不是真的参数,在宏展开的时候对“参数”进行的是一对一的替换。  
程序员对宏定义的使用要非常小心,特别要注意两个问题:  
(1)谨慎地将宏定义中的“参数”和整个宏用用括弧括起来。所以,严格地讲,下述解答:  
#define MIN(A,B)    (A) <=  (B) ? (A) : (B)  
#define MIN(A,B)    (A <=  B ? A : B )  
都应判0分;  
(2)防止宏的副作用。  
宏定义#define MIN(A,B)   ((A) <=  (B) ? (A) : (B))对MIN(*p++, b)的作用结果是:  
((*p++) <=  (b) ? (*p++) : (*p++))  
这个表达式会产生副作用,指针p会作三次++自增操作。  
除此之外,另一个应该判0分的解答是:  
#define MIN(A,B)    ((A) <=  (B) ? (A) : (B));这个解答在宏定义的后面加“;”,显示编写者对宏的概念模糊不清

试题11:为什么标准头文件都有类似以下的结构?  
   #ifndef __INCvxWorksh  
   #define __INCvxWorksh  
   #ifdef __cplusplus  
   extern "C" {  
   #endif  
   /*...*/  
   #ifdef __cplusplus     } 
   #endif  
   #endif /* __INCvxWorksh */  
   解答: 
头文件中的编译宏 
#ifndef __INCvxWorksh 

#define __INCvxWorksh 

#endif  的作用是防止被重复引用。  
作为一种面向对象的语言,C++支持函数重载,而过程式语言C则不支持。函数被C++编译后在symbol库中的名字与C语言的不同。例如,假设某个函数的原型为:  
void foo(int x, int y);  
该函数被C编译器编译后在symbol库中的名字为_foo,而C++编译器则会产生像_foo_int_int之类的名字。_foo_int_int这样的名字包含了函数名和函数参数数量及类型信息,C++就是考这种机制来实现函数重载的。  
为了实现C和C++的混合编程,C++提供了C连接交换指定符号extern "C"来解决名字匹配问题,函数声明前加上extern "C"后,则编译器就会按照C语言的方式将该函数编译为_foo,这样C语言中就可以调用C++的函数了。

试题12:编写类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::~String(void)               // 3分

{

    delete [] m_data;                     

// 由于m_data是内部数据类型,也可以写成 delete m_data;

       }

 

       //String的普通构造函数            

       String::String(constchar *str)      // 6分

{

    if(str==NULL)                         

    {

       m_data = new char[1];    // 若能加 NULL 判断则更好

       *m_data = ‘\0’;                     

    }                                         

    else

    {

       int length = strlen(str);          

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

       strcpy(m_data, str);               

    }

}  

// 拷贝构造函数

    String::String(constString &other)   // 3分

    {  

    int length = strlen(other.m_data);

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

    strcpy(m_data, other.m_data);        

}

// 赋值函数

    String &String::operate =(const String &other)   // 13分

    {  

       // (1) 检查自赋值                     // 4分

       if(this ==&other)

           return*this;

   

// (2)释放原有的内存资源            // 3分

       delete []m_data;

      

       // (3)分配新的内存资源,并复制内容 // 3分

    int length = strlen(other.m_data);

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

        strcpy(m_data, other.m_data);

      

       // (4)返回本对象的引用            // 3分

       return *this;

}   

能够准确无误地编写出String类的构造函数、拷贝构造函数、赋值函数和析构函数的面试者至少已经具备了C++基本功的60%以上!  
在这个类中包括了指针类成员变量m_data,当类中包括指针类成员变量时,一定要重载其拷贝构造函数、赋值函数和析构函数,这既是对C++程序员的基本要求,也是《Effective C++》中特别强调的条款。

试题13:

请说出static和const关键字尽可能多的作用  
解答:  
static关键字至少有下列n个作用:  
(1)函数体内static变量的作用范围为该函数体,不同于auto变量,该变量的内存只被分配一次,因此其值在下次调用时仍维持上次的值;  
(2)在模块内的static全局变量可以被模块内所用函数访问,但不能被模块外其它函数访问;  
(3)在模块内的static函数只可被这一模块内的其它函数调用,这个函数的使用范围被限制在声明它的模块内;  
(4)在类中的static成员变量属于整个类所拥有,对类的所有对象只有一份拷贝;  
(5)在类中的static成员函数属于整个类所拥有,这个函数不接收this指针,因而只能访问类的static成员变量。  
const关键字至少有下列n个作用: 
(1)欲阻止一个变量被改变,可以使用const关键字。在定义该const变量时,通常需要对它进行初始化,因为以后没有机会再去改变它。
(2)对指针来说,可以指定指针本身为const,也可以指定指针所指的数据为const,或二者同时指定为const; 
(3)在一个函数声明中,const可以修饰形参,表明它是一个输入参数,在函数内部不能改变其值; 
(4)对于类的成员函数,若指定其为const类型,则表明其是一个常函数,不能修改类的成员变量; 
(5)对于类的成员函数,有时候必须指定其返回值为const类型,以使得其返回值不为“左值”。例如: 
const classA operator*(const classA& a1,const classA& a2); 
operator*的返回结果必须是一个const对象。如果不是,这样的变态代码也不会编译出错: classA a, b, c; (a * b) = c; // 对a*b的结果赋值  
操作(a * b) = c显然不符合编程者的初衷,也没有任何意义。

试题14:写一个函数返回1+2+3+…+n的值(假定结果不会超过长整型变量的范围) 解答: 
int Sum( int n ) {  
       return  ( (long)1 + n) * n / 2;  //或return  (1l + n) * n / 2; }





  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值