C/C++面试题-1

1. C语言中的 sizeof 问题
(1)类型转换的问题

复制代码
    #include <stdio.h>  
     #define NUM (sizeof(arr) / sizeof(arr[0]))        
     int arr[] = {  1,  2,  3,  4,  5,  6,  7 };        
     int main()  
    {  
         int i;         
         for( i = - 1; i <= ( NUM -  2 ); i++)  
        {       
        printf( " %d\n ",arr[i+ 1]);  
        }            
         return  0;  
    } 
复制代码


输出的结果是空的!
解释:我们要知道的是:sizeof 返回的是一个unsinged int的值!那么在for循环的时候,i = -1就会向后面转型,将其值转化为sizeof的值,那么我们很清楚,-1转化的sizeof的值是很大的一个正整数!那么很显然就直接不符合i <= ( NUM - 2 )的条件了,所以就不会输出!!!
(2)sizeof是操作符

复制代码
    #include <stdio.h>  
     int main()  
    {  
         int i;  
        i =  10;        
        printf( " i : %d\n ",i);  
        printf( " sizeof(i++) is: %d\n ", sizeof(i++));  
        printf( " i : %d\n ",i);  
           return  0;  
    } 
复制代码


结果是
 i : 10
 sizeof(i++) is: 4
 i : 10
为什么第三个还是输出10呢?!
解释:解决这个问题就是要理解编译器编译原理。 我们要知道sizeof仅仅是一个操作符而已并不是函数,sizeof要做的仅仅是获得i++的字节数,那么所以在编译的时候就直接用4代替了i++了,反正编译器知道结果都是一样,所以最终i++并没有执行!

2. 非C++内建型别 A 和 B,在哪几种情况下B能隐式转化为A?[C++中等]
答:

a.  class B :  public A { ……}  //  B公有继承自A,可以是间接继承的
b.  class B {  operator A( ); }  //  B实现了隐式转化为A的转化
c.  class A { A(  const B& ); }  //  A实现了non-explicit的参数为B(可以有其他带默认值的参数)构造函数
d. A&  operator= (  const A& );  //  赋值操作,虽不是正宗的隐式类型转换,但也可以勉强算一个 

 

3. C++对象声明的陷阱

复制代码
struct Test
{
    Test(  int ) {}
    Test() {}
     void fun() {}
};
void main(  void )
{
    Test a( 1);
    a.fun();
    Test b(); // 这儿的问题,C++中默认构造函数生成实例不用加括号,如果加上括号这儿就像定义了一个函数
    b.fun();
}
复制代码

4. 以下代码有什么问题?[C++易]
cout << (true?1:"1") << endl;
这儿条件操作符中的前后的类型要一致
一个条件操作符是下面这样的形式:
exp1 ? exp2 : exp3
表达式exp1总是会被求值。exp2和exp3是否被执行依赖于exp1的值,如果exp1为真则exp2会被求值,否则exp3被求值。
Side Effect:
在执行exp2或者exp3之前,exp1的所有side effect必须全部求值或者更新完成,因为条件操作符的第一个操作数求值之后就是一个sequence point。如果exp2和exp3都有side effect,那么只有一个会被求值。
返回类型:
条件操作符的返回类型取决于exp2和exp3类型,编译器会检查exp2(可能是一个class type)能否转换为exp3或者exp3能否转换为exp2,如果两个都不满足,编译器就会抛出一个错误。

5. C++中的空类,默认产生哪些类成员函数?[C++易]
答:

复制代码
class Empty
{
public:
    Empty();                           //  缺省构造函数
    Empty(  const Empty& );             //  拷贝构造函数
    ~Empty();                          //  析构函数
    Empty&  operator=(  const Empty& );  //  赋值运算符
    Empty*  operator&();                //  取址运算符
     const Empty*  operator&()  const;    //  取址运算符 const
};
复制代码

 

6. 转换为引用类型:浮点数内存表示

复制代码
    float a =  1.0f;
   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;
复制代码

问:上述代码的输出结果是什么?
这种转换为引用类型的情况的确比较少见,但有些时候必须用它!(EC++ 3rd)中讲解copy assignment operator时就提到过一种必须用它的情形。大概需要记住的就是,转向普通类型,则返回的其实是一个为你新创建的临时对象;而转换为引用类型,则返回的其实是你要转换的那个对象本身,只是reinterpret了一下而已,原来的对象内容也没改变。
"转换为引用类型"操作的本质: "(int&)a 等价于 *(int*)(&a); 就是把原始a 的内存里面数据按照整形输出。因此不等价于(int)a;"
另外的解释:(int&)a 不经过转换, 直接得到a在内存单元的值,并将其转换成整数输出。

 

7. C语言字符串与字符数组

以下输出语句分别输出什么?[C易]

复制代码
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 ";
char* str9 =  " efg ";
char* str0 =  " efg ";
cout<< " str1= "<<( void*)str1<< "   "<< " str2= "<<( void*)str2<< "   ";
cout << boolalpha << ( str1==str2 ) << endl;  //  输出什么?
cout<< " str3= "<<( void*)str3<< "   "<< " str4= "<<( void*)str4<< "   ";
cout << boolalpha << ( str3==str4 ) << endl;  //  输出什么?
cout<< " str5= "<<( void*)str5<< "   "<< " str6= "<<( void*)str6<< "   ";
cout << boolalpha << ( str5==str6 ) << endl;  //  输出什
cout<< " str7= "<<( void*)str7<< "   "<< " str8= "<<( void*)str8<< "   ";
cout << boolalpha << ( str7==str8 ) << endl;  //  输出什
cout<< " str9= "<<( void*)str9<< "   "<< " str0= "<<( void*)str0<< "   ";
cout << boolalpha << ( str9==str0 ) << endl;  //  输出什 
复制代码

在linux平台下的结果是:

这个应该比较好理解,数组是要分配空间的,因为它的内容是可以改变的,所以地址是不同的。而字符串是不允许改变的,相同的字符串应该是统一存放的。

 

8. 其他类型到bool的隐式转换

下面的代码输出是什么?

复制代码
#include <iostream>
#include < string>
using  namespace std ;
void a( bool input) {
cout <<  " I amd first " <<endl;
cout <<input <<endl ;
}
void a( const  string &input) {
cout<<  " I amd second " <<endl ;
cout<<input <<endl ;
}
int main(  int argc,  char **argv)
{
a( " str ") ;  //  是调用第二个a函数吗?
a( string( " str ")) ;
return  0 ;
}
复制代码

 

输出结果竟然是:

char*类型的"str"居然被隐式转化成了bool类型

然后做实验验证一下:

复制代码
#include < string>
using  namespace std;
int main( int argc,  const  char *argv [])
{
int a = 1;
char *b=  " wo ";
float c =  1.1;
bool x ;
x = a;
x = b;
x = c;
return  0;
}
复制代码

 

int,char*,float确实都可以隐式转化成bool而不会有任何警告,导致出现问题很不容易发现,这里在重载函数的时候确实需要万分注意。

 

9. 堆排序在大数据中的应用

堆排序的时间复杂度为O(nlogn),最坏的情况也是这个时间复杂度,空间复杂度是O(1)。但是堆排序是不稳定的!

在面试过程中,很多时候都会用到堆排序,比如下面的题目都是堆排序的典型题目:

1.给你100w个数据求最大的10个元素。这个时候我们可以使用小顶堆!这个是为什么呢!

2.给你100w个数据求最小的10个元素。这个时候我们可以使用大顶堆!这个是为什么呢!

相信会有很多同学会问出上面的两个疑问,答案其实很简单,在求最大的元素的时候,我们建立一个有10个元素的小顶堆,那么堆顶元素肯定是最小的,然后拿剩余的元素和堆顶进行比较,如果比堆顶大,就替换这个元素,然后调整堆,调整完之后堆顶依然是10个元素中最小的,依次比较剩余的元素。

堆排序与直接插入排序的区别

直接选择排序中,为了从R[1..n]中选出关键字最小的记录,必须进行n-1次比较,然后在R[2..n]中选出关键字最小的记录,又需要做n-2次比 较。事实上,后面的n-2次比较中,有许多比较可能在前面的n-1次比较中已经做过,但由于前一趟排序时未保留这些比较结果,所以后一趟排序时又重复执行 了这些比较操作。 堆排序可通过树形结构保存部分比较结果,可减少比较次数。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值