博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C/C++面试题-1
阅读量:5972 次
发布时间:2019-06-19

本文共 4652 字,大约阅读时间需要 15 分钟。

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次比较中已经做过,但由于前一趟排序时未保留这些比较结果,所以后一趟排序时又重复执行 了这些比较操作。 堆排序可通过树形结构保存部分比较结果,可减少比较次数。

转载于:https://www.cnblogs.com/xkfz007/archive/2012/08/25/2656940.html

你可能感兴趣的文章
递归算法,如何把list中父子类对象递归成树
查看>>
hdu 1050 (preinitilization or postcleansing, std::fill) ...
查看>>
Linux vmstat命令实战详解
查看>>
我的友情链接
查看>>
替换k个字符后最长重复子串
查看>>
讲解sed用法入门帖子
查看>>
Java异常学习心得
查看>>
Scala学习之类和属性篇(一):定义类的主构造方法
查看>>
使用阿里云CentOS安装LAMP时,安装PHP扩展需要注意的事情
查看>>
Linux 内核已支持苹果
查看>>
shell脚本逻辑判断,文件目录属性判断,if,case用法
查看>>
【二叉树系列】二叉树课程大作业
查看>>
JAVA spring配置文件总结
查看>>
Java5的 线程并发库
查看>>
HDOJ 1036 输入输出 水
查看>>
Java 安装后的检测是否安装成功
查看>>
设备及分辨率
查看>>
mybatis拦截器
查看>>
App重新启动
查看>>
矩阵乘法
查看>>