您的位置:首页 > 编程语言 > C语言/C++

C/C++笔试面试(3)

2014-05-20 19:09 253 查看
1.下面C++代码输出结果是什么?
 int i=1;
 void main()
{
int i=i;
}

答案:main()里的i是一个未定义的值。

2.下面程序的结果是多少?
#include<iostream>
using namespace std;
int main()
{
int x=2,y,z;
x*=(y=z=5);cout<<x<<endl;
z=3;
x==(y=z);cout<<x<<endl;
x=(y==z);cout<<x<<endl;
x=(y&z);cout<<x<<endl;
x=(y&&z);cout<<x<<endl;
y=4;
x=(y|z);cout<<x<<endl;
x=(y||z);cout<<x<<endl;
return 0;
}

答案:10 10 1 3 1 7 1

表达式详细解释x值
x*=(y=z=5)5赋值给z,z再赋值给y,x=x*y10
x==(y=z)z赋值给y,然后再看想,x,y是否相等。不管相等与否x值不变10
x=(y==z)首先判断y、z是否相等,相等则返回一个布尔值11
x=(y&z)y、z按位与运算3
x=(y&&z)&&是指如果y为真,z为真,则(y&&z)为真,返回一个布尔值11
x=(y|z)按位或运算7
x=(y||z)||表示有一个为真,则y||z为真,返回一个布尔值11
&与运算

y0011
z0011
y&z0011
|或运算

y0100
z0011
y|z0111
^异或运算

y1100
z1001
y^z0101
移位运算>> <<

<<1左移一位表示乘以2
>>1右移一位表示除以2
3.以下代码的结果是多少?
#include <iostream>
using namespace std;
int func(int x)
{
int count=0;
while(x)
{
count++;
x=x&(x-1);
        }
return count;
}
int main()
{
count<<func(9999)<<endl;
return 0;
}
答案:8
详细解析:func函数返回值是形参x转换成二进制后包含1的个数,9999的二进制是10011100001111

拓展题:用一个表达式,判断一个数x是否是2^N次方(2,4,8……),不可用循环语句

解析:2、4、6、8转化成二进制是10、100、1000、10000如果x减1后与x做与运算,答案若是0,则是2^N次方
答案:!(x&(x-1))

4.关于sizeof的一系列题目

4.1下面代码的输出结果是什么?(一维数组、结构体、指针)
#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
struct{
short a1;
short a2;
short a3;
}A;
struct{
long a1;
short a2;
}B;
int main()
{
char* ss1="0123456789";
char ss2[]="0123456789";
char ss3[100]="0123456789";
int ss4[100];
char q1[]="abc";
char q2[]="a\n";
char* q3="a\n";
char *str1=(char *)malloc(100);
void *str2=(void *)malloc(100);
cout<<sizeof(ss1);
cout<<sizeof(ss2);
cout<<sizeof(ss3);
cout<<sizeof(ss4);
cout<<sizeof(q1);
cout<<sizeof(q2);
cout<<sizeof(q3);
cout<<sizeof(A);
cout<<sizeof(B);
cout<<sizeof(str1);
cout<<sizeof(str2);
return 0;   
}

答案:4,11,100,400,4,3,4,6,8,4,4

xxx详细解释sizeof(xxx)
ss1字符指针,指针大小就是一个定值,就是4字节4
ss2最初未定大小的字符数组,10个字节再加上隐含的"\0"(10+1)11
ss3字符数组开始预分配100,大小1*100100
ss4整形数组开始预分配100,大小4*100400
q1类似ss2 3+14
q2同上3
q3字符指针就是定值为44
A关于结构大小参看博客26
B同上8
str1字符指针就是定值为4
4
str2字符指针就是定值为4
4
4.2关于sizeof和strlen差异的题目。

(1)char ss[100]="0123456789";
   sizeof(ss)=1*100
   strlen(ss)=10;//它的内部实现是用一个循环计算字符串的长度,直到"\0"为止。
(2)int ss[100]="0123456789";
   sizeof(ss)=4*100
   strlen(ss)报错,注意strlen的参数只能是char*

4.3下面代码输出结果是多少?
char var[10];
int test(char var[])
{
return sizeof(var);
};
A:10B:9C:11D:4

答案:D
解析:因为var[]等价于*var,已经退化成一个指针了,大小为4
拓展:数组作为参数传给函数时传的是指针而不是数组,传递的是数组的首地址,如fun(char[8])、fun(char [])都等价于fun(char *);;对函数使用sizeof,在编译阶段会被函数返回类型取代如:
int f1(){return 0;}
cout<<sizeof(f1())<<endl;//f1返回值为int,因此被认为是int

     4.4(1)int **a[3][4]数组占据多大空间?(二维数组、unsigned、自定义类型)

sizeof(a)=3*4*4=48

(2) unsigned影响只是最高位bit的意义(正负),数据长度不会被改变的。所以:

sizeof(unsigned int)==sizeof(int)

(3)自定义类型的sizeof取值等同于它的类型原型

typedef short WORD;

sizeof(short)==sizeof(WORD)

4.5找出下面程序的错误,并解释它为什么是错的?

#include<iostream>

#include<string>

using namespace std;

int main(int argc,char *argv[])

{

//为输出"TrendMicroSoftUSCN"

string strArr1[]={"Trend","Micro","Soft"};

string *pStrArr1=new string[2];

`pStrArr1[0]="US";

pStrArr1[1]="CN";

for(int i=0;i<sizeof(strArr1)/sizeof(string);i++)

cout<<strArr1[i];

for(int j=0;j<sizeof(pStrArr1)/sizeof(string);j++)

cout<<pStrArr1[j];

return 0;

}

程序运行后输出:TrendMicroSoftUS

原因:sizeof(strArr1)=12;sizeof(pStrArr1)=4即指针大小当然不能正常输出;

应该为:for(int j=0;j<sizeof(pStrArr1)*2/sizeof(string);j++)

4.6类、继承、虚函数等中的sizeof问题
(1)写出下面sizeof的答案。
#include<iostream>
#include<complex>
using namespace std;
class Base
{
public:
Base(){cout<<"Base-ctor"<<endl;}
~Base(){cout<<"Base-dtor"<<endl;}
virtual void f(int){cout<<"Base::f(int)"<<endl;}
virtual void f(double){cout<<"Base::f(double)"<<endl;}
virtual void g(int i=10){cout<<"Base::g()"<<i<<endl;}
void g2(int i=10){cout<<"Base::g2()"<<i<<endl;}
};
class Derived:public Base
{
public:
Derived(){cout<<"Derived-ctor"<<endl;}
~Derived(){cout<<"Derived-dtor"<<endl;}
void f(complex<double>){cout<<"Derived::f(complex)"<<endl;}
virtual void g(int i=20){cout<<"Derived::g()"<<i<<endl;}
};
int main()
{
Base b;
Derived d;
Base* pb=new Derived;
cout<<sizeof(Base)<<endl;//答案:4
cout<<sizeof(Derived)<<endl;//答案:4
}

(2)一个空类占多少空间?多重继承的空类呢?
#include<iostream>
#include<memery.h>
#include<assert.h>
using namespace std;
class A
{
};
class A2
{
};
class B:public A
{
};
class C:public virtual B
{
};
class D:public A,public A2
{
};
int main()
{
cout<<sizeof(A)<<endl;//1
cout<<sizeof(B)<<endl;//1
cout<<sizeof(C)<<endl;//4
cout<<sizeof(D)<<endl;//1
}
空类所占空间是1,单一继承1,多重继承1,虚函数涉及虚指针大小为4

5.下面两段代码输出结果有什么不同?

第1段:
#include<iostream>
using namespace std;
int main()
{
int a,x;
for(a=0,x=0;a<=1&&!x++;a++)
{
a++;
        }
cout<<a<<x<<endl;
return 0;
}

第2段:
#include<iostream>
using namespace std;
int main()
{
int a,x;
for(a=0,x=0;a<=1&&!x++;)
        {
a++;
}
cout<<a<<x<<endl;
return 0;
}

第1段输出结果:21
第2段输出结果:12

详细解析:

执行第1段代码第2段代码
第一步初始化定义a=0,x=0初始化定义a=0,x=0
第二步a小于等于1,x的非为1,符合循环条件a小于等于1,x的非为1,符合循环条件
第三步x++后x自增为1x++后x自增为1
第四步进去循环体,a++,a自增为1进去循环体,a++,a自增为1
第五步执行for(a=0,x=0;a<=1&&!x++;a++)中a++,a自增为2a现在是1符合小于等于1条件,x现在是1,x的非为0,不执行循环体,但x++依然执行自增为2
第六步a现在是2,已经不符合小于等于1条件了“&&”后的“!x++”不执行x还是1不执行循环体打印12
6.面试笔试中两个数a和b的问题
(1)有两个变量a和b,不用“if”,"?:","switch"或其他判断语句,找出两个数中比较大的数。
答案:int max=((a+b)+abs(a-b))/2

(2)将a和b的值进行交换,并且不使用任何中间变量。
答案:a=a^b;
     b=a^b;
     a=a^b;

亦可以这么做不过会有a=a+b超界问题:
a=a+b;
b=a-b;
a=a-b;

7.笔试面试中需要注意的一些常识性问题
(1).在C++程序中调用C编译器编译后函数,为什么要加extern “C”?
答:C++提供了C连接交换指定符号extern “C”解决了名字匹配问题
原因:C++支持函数重载,C不支持函数重载。函数被C++编译后在库中名字与C语言不同。假设某个函数原型为
void foo(int x,int y),该函数被C编译器编译后在库中名字为_foo,而在C++编译器中编译则会产 生像_foo_int_int之类的名字

(2).头文件中的ifndef/define/endif是干什么用的?
答:防止头文件被重复引用。
(3)*(ptr++)+=123;等价于*ptr=*ptr+123;ptr++;

(4)const那些事儿:
可以用const修饰对象、数据成员和成员函数;常数据成员只能由构造函数由初始化列表对其进行初始化;常对象只能调用类的常成员函数,不能调用非常成员函数;
const有什么用途?
答案:(1)可以定义const变量(2)const可以修饰函数参数和返回值,甚至函数定义体。被const修饰的东西都受到了强制保护,可以预防意外变动,能提高程序健壮性。
注意:const常量赋值时必需同时初始化。const double di=10.0;//正确
                                const double  di;//错误没有初始化 
拓展:const与#define相比有什么不同
C++程序中只使用const常量而不使用宏常量C迫使程序员在预处理里使用#define,前者比后者有更多的优点:(1)const有数据类型,而宏常量没有数据类型(2)有的调试工具可以对const常量进行调试,但不能对宏常量进行调试。另外,在const成员函数中,用mutable修饰成员变量名后,就可以修改类的成员变量了。

(5)内联函数和宏的差别是什么?
答案:内联函数和普通函数相比可以加快程序的运行速度,因为不需要中断调用,在编译的时候内联函数可以直接被镶嵌到目标代码中。而宏只是一个简单地替换。
拓展:inline函数一般只用于如下情况:
(1)一个函数不断被重复调用
(2)函数只有简单地几行,且函数内不包含for、while、switch语句

(6)指针和引用的差异。
答案:1.非空区别。声明一个引用,但引用不能为空,必须同时初始化,不可以使用指向空值引用,因此代码效率比使用指针高。

例如:int iv;   int &reiv=iv;//正确!
     int &reiv;//错误用法 声明一个引用必须进行初始化。

     2.合法性区别。使用引用不需要测试合法性。
     3.可修改区别。指针可以被重新赋值指向另一个对象。

(7)C++有了malloc/free,为什么还要用new/delete?

答案:malloc与free是C/C++标准库函数,new/delete是C++运算符。他们都可以申请动态内存和释放内存。对非内部数据类型的对象而言,只用malloc/free无法满足动态对象的要求。
new/delete知多少:
运算符new可以用来动态创建对象和对象数组;使用new创建对象时会调用类的构造函数,也可以用delete析构;

8.面试中预处理问题

8.1用一个宏定义FIND求一个结构体struc里某个变量相对struc的偏移量
{
int a;
char b[20];
double ccc;
}
则:FIND(student,a);//等于0
   FIND(student,b);//等于4

答案:#define FIND(struc,e) (size_t)&(((struc*)0)->e)
解析:其中(struc*)0表示将常量0强制转化为struc*型指针所指向的地址;&(((struc*)0)->e)表示取结构体(struc*)0的成员e的地址,因为该结构体的首地址为0,所以其实就是得到了成员e距离结构体首地址的偏移量。(size_t)是一种数据类型,为了便于不同系统之间移植,最好定义为一种无符号型数据,一般为unsigned
int.

8.2写一个标准宏定义MIN,这个宏定义输入两个参数并返回较小的一个。
答案:#define MIN(A,B) ((A)<=(B)?(A):(B))

8.3下面程序的运行结果是什么?

#include<stdio.h>
# define ADD(x) x+x
void main()
{
int m=1,n=2,k=3;
int sum=ADD(m+n)*k;
printf("%d",sum);
}
输出结果:10
注意:宏定义表达式最好都加上括号,只是简单的代码兑换;本代码中ADD(m+n)替换为m+n+m+n,没有括号就是m+n+m+n*k=10
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  c语言