Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2206153
  • 博文数量: 866
  • 博客积分: 14125
  • 博客等级: 上将
  • 技术积分: 10638
  • 用 户 组: 普通用户
  • 注册时间: 2007-07-27 16:53
个人简介

https://github.com/landuochong

文章分类

全部博文(866)

文章存档

2019年(3)

2018年(1)

2017年(10)

2015年(3)

2014年(8)

2013年(3)

2012年(70)

2011年(103)

2010年(360)

2009年(283)

2008年(22)

分类: C/C++

2010-10-09 09:26:55

电话面试
1:虚函数原理?有何用?(辅助实现设计模式)
    虚表,编译器绑定到虚表中的指定项。
    同样虚函数也如此,编译器已经算好了虚函数在虚表中的位置。只是由于只是由于每个类的指向虚表的指针不一样,才产生了多态的行为。
2:指针背后的秘密?
   指针能指向东西,是因为编译期,编译器已经算好了指针指向成员变量的偏移地址,所以其能实现指向某个东西的能力。
2:了解哪些设计模式?举例。比如项目中用到的。
1:select epool。
2:c99的标准 对数组有什么增强?
面对面面
3:应用层如何到达网络层。|
4:有100万个文件,如果通过shell删除其中以filename开头的文件
5:http对一个域名最多几个并发请求
6:如何调整消息队列大小?如何调整共享内存大小?
7:time_wait包如何产生,如何快速的回收
8:listen中backlog的含义
9:long long如何网络序列化?
10:写一个strlen函数,写一个折半查找函数,
11:多进程和多线程的差别,
12:如何优化程序?有无程序优化的经验?
      查看系统性能,那个线程占用cpu多。
13:大量的问你曾经做过的项目?
   代码量,你扮演的角色,项目经验教训,架构实现,多线程通信,多进程通信架构。
经理面
1有两个很长的字符串,找出在第一个字符串里面出现过,在第二个里面没有出现的字母。
2两个psp楼上摔。(一步一步引导你)
3你三个擅长的地方三个害怕的地方
4问毕业设计(他不懂,就瞎问的)
人力面
1为何辞职?
2如何能给我证明你编程能力?
3为何简历中不突出你的获奖经历?
4职业规划?
 
 
第一题是描述树的深度遍历,广度遍历和非递归实现的特点。基本数据结构,简单。
    第二题是改错。程序如下:
  1 typedef {
2     int num;
3     int imag;
4 }Complex_t;
5
6 int alloc(Complext_t * a,int num){
7     a=new Complex_t[num];
8     if(a==NULL){
9         return -1;
10     }
11     return 0;
12 }
13
14 unsigned long long compute(){
15     Complext_t * a;
16     int num,pos;
17     unsigned long long sum;
18     cin>>num;
19     if(alloc(a,num)<0){
20         return -1;
21     }
22
23
24     cin>>pos;
25     while(pos26         cin>>a[pos].num>>a[pos].imag;
27         cin>>a[pos+1].num>>a[pos+1].imag;
28         sum+=a[pos].num*a[pos].num+a[pos].imag*a[pos].imag;
29         sum+=a[pos+1].num*a[pos+1].num+a[pos+1].imag*a[pos+1].imag;
30         pos+=2;
31     }
32     return sum;
33 }
大概是这样吧。我找出下面错误。
第六行:Complex_t *变为Complex_t * &
去掉第八至第九行。因为根据C++99new不再返回NULL,而是throw std::bad_alloc
18行的cin没有检查cin.fail()是不是返回true
19行应该用try...catch围绕
24同理于18行
25行的条件可能导致越界访问,所以应该改为pos26,27同理于18行
第三题就开始有点难了,我是最后才做出来的。问题是一个1K内存和1MHz和CPU(意味着它1秒钟能改变10^6次状态),问如何在不死循环的条件下让它最长时间的运行,而且是因为某个状态退出的。可以假设你的条件。
一 开始我毫无头绪。最后终于醒悟,应该用最最底层的办法做。就是在内存放着一段代码,就这样让它跑。怎么让它跑得最长又不死循环呢?我想应该是让除了代码之 外的所有内存在一个周期内加一位,也就是说把剩下的内存看作一个巨大的整型,正如int是32位一样,这个内存区域是XXX位。好了,我假设CPU是16 位的8086,初始状态寄存器全部是0(考试的时候我犯傻了,居然写32位x86)。
程序段放如下编码:
start:   
inc al 1B
jno start 3B;不溢出则重新增加
xor cx,cx 2B
overflow:
movb al,[data_start+cx] 3B;data_start是数据起始地址
inc al 1B
movb [data_start+cx],al 3B
xor ax,ax    2B
jno start 3B
inc cx 1B
jmp overflow 3B
于 是代码段使用了1+3+2+3+1+3+2+3+1+3=22B,还剩1024-22=1002B内存用于数据存储。另外还有1B的寄存器,所以是 1003B的存储区域。另外假设改变内存状态和改变寄存器状态一样只花一个周期,还有忽略别的消耗(比如上面的xor cx,cx)这样状态会改变2^1003次,所以最长时间为2^(8*1003)/10^6。上面这段代码会在越界访问的时候退出。
然后就到了算法题;第一题说的是编译依赖问题。说的是一个系统有N个组件组成,N个组件之间有依赖关系。为了解决依赖,必须确定编译的顺序。问算法。
其 实这是著名的穿衣问题,问题是一个人有内裤,裤子皮带……这些东西,问人应该怎么穿才能不变成超人!所以解决方法也是一样的,就是拓扑排序。拓扑排序是先 对图中所有子节点进行广度优先的遍历(郑K说是深度遍历,我敢肯定他错了,因为深度遍历得到的是一棵树,而不是几棵,依赖关系可能不只是一棵树的),然后 在遍历同时标记遍历的起始时间和结束时间,然后对起始时间进行排序。
第二题是编程题。实现的是从字符串返回一个具有最长连续数字的子字符串

问 有10个瓶子,每个瓶子里面装了100个药,其中有9个瓶子里面的药都是合格的,重量1g。而有一个瓶子里面的药全部不合格,全部重1.01g. 单具体哪一个瓶子里的药不合格是未知的。

1:现有一把秤(注意,不是天平),如何一次性称重得出是哪个瓶子里的药不合格?
2:如果有多个瓶子里的药不合格,如何一次性称重得出是哪些瓶子里的药不合格?
 
1:
#i nclude
union
{
int i;
char x[2];
}a;

void main()
{
a.x[0] = 10;
a.x[1] = 1;
printf("%d",a.i);
}
答案:266 (低位低地址,高位高地址,内存占用情况是Ox010A)
2:(微软笔试题)
int func(x)
{
int countx = 0;
while(x)
{
countx ++;
x = x&(x-1);
}
return countx;
}
假定x = 9999。 答案:8
思路:将x转化为2进制,看含有的1的个数。
3:不用比较算符,不用if,得出int a, b的较大者。
   解决方案1:
   这个貌似是终极方案了:
   #define MyMax(a, b) (((a)-(b))&0x80000000 ? (b) : (a) )
   cout<

    解决方案2:(爽哥提供的方案)
 char* str_vec[2];
 str_vec[0] = "a>=b";
 str_vec[1] = "a
 int a = 10;
 int b = 11;
 int idx = (unsigned int)(a-b)>>31;  // 要转化为无符号数
 cout<

 
4:
C++中不能重载的算符有:“.”、“::”和“sizeof” 3个.
另外“?:”算符由于重载的话没有意义,一般也不让重载。
5:
  再给出常用的C变量的定义方式:
  a) 一个整型数(An integer)
  b) 一个指向整型数的指针(A pointer to an integer)
  c) 一个指向指针的的指针,它指向的指针是指向一个整型数(A pointer to a pointer to an integer)
  d) 一个有10个整型数的数组(An array of 10 integers)
  e) 一个有10个指针的数组,该指针是指向一个整型数的(An array of 10 pointers to integers)
  f) 一个指向有10个整型数数组的指针(A pointer to an array of 10 integers)
  g) 一个指向函数的指针,该函数有一个整型参数并返回一个整型数(A pointer to a function that takes an integer as an argument and returns an integer)
  h) 一个有10个指针的数组,该指针指向一个函数,该函数有一个整型参数并返回一个整型数( An array of ten pointers to functions that take an integer argument and return an integer )
  答案是:
  a) int a; // An integer
  b) int *a; // A pointer to an integer
  c) int **a; // A pointer to a pointer to an integer
  d) int a[10]; // An array of 10 integers
  e) int *a[10]; // An array of 10 pointers to integers
  f) int (*a)[10]; // A pointer to an array of 10 integers
  g) int (*a)(int); // A pointer to a function a that takes an integer argument and returns an integer
  h) int (*a[10])(int); // An array of 10 pointers to functions that take an integer argument and return an integer
     // 扩展1 函数指针数组
     定义一个10个元素的数组,元素是函数指针,函数的参数为(int,int),返回值为int
     方法1:int (*p[10])(int,int);
     方法2:typedef int (*PFUN)(int,int)
                PFUN p[10];
                // 使用方法
                p[0](1,1);
                p[1](1,1);
     函数指针数组的应用:
    
http://zhidao.baidu.com/question/50580445.html
  
     // 扩展2 指向函数指针数组的指针
     方法1:int (*(*ppfun)[2])(int,int);
                ps:将方法2中的3)式代入1)式中即可得到
     方法2:typedef int (*PFUN)(int,int) // ----------------------------------------------1)
                PFUN p[10];                        // 函数指针数组--------------------------------2)
                PFUN (*pp)[10] = &p;         // 指向函数指针数组的指针--------------------3)
                // 使用方法
                (*pp)[0](1,1);
                (*pp)[1](1,1);
       参考资料:
      
http://topic.csdn.net/t/20030127/20/1396208.html
       如果你觉得你懂了,那么做下面的题:
       (1) float(**def)[10]   def是什么?
       (2) double*(*gh)[10]   gh是什么?
       (3) double(*f[10])()   f是什么?
       (4) int*((*b)[10])    b是什么?
       (5) int(*(*f)(int,int))(int) f是什么?
答案:
(1) def是一个指针, 指向的对象也是一个指针, 指向的指针最终指向的是10个float构成的数组.
(2) gh是指针, 指向的是10个元素构成的数组, 数组的元素是double*类型的指针.
(3) f是10个元素构成的数组, 每个元素是指针, 指针指向的是函数, 函数类型为无参数且返回值为double. 下面要讲的窍门的例子跟这个很类似.
(4) b是指针,指向的是10个元素构成的数组, 数组元素为int*类型的指针.
(5)f是一个函数指针,指向的函数是具有两个int型参数并返回一个函数指针的函数,返回的函数指针指向一个有一个int参数并返回int的函数
呵呵,做这样的题是不是有点崩溃???下面介绍一个好方法。
窍门如下:
如果我们碰到复杂的类型声明,该如何解析它?例如:
char (*a[3])(int);
a到底被声明为什么东东?指针?数组?还是函数?
分析时,从a 最接近(按运算符优先级)处开始。我们看到a最接近符号是[ ]——注意:*比[ ]的优先级低。a后既然有[ ],那么a是数组,而且是包含3个元素的数组。
那这个数组的每个元素是什么类型呢?虽然数组a只含有a[0]、a[1]、a[2]三个元素,a[3]实际上已经越界,但在分析数组a的元素的类型时,我们正好需要形式上的元素a[3]。知道了a[3]的类型,就知道了a的元素的类型。 a[3]是什么类型?是指针,因为它的前面有*. 由此可知,数组a的元素是指针。
光说是指针还不够。对于指针,必须说出它指向的东东是什么类型。它指向的东东是什么,就看*a[3]是什么(a[3]是指针,它指向的东东当然是*a[3])了。继续按优先级观察,我们看到*a[3]后面有小括号,所以可以肯定*a[3]是函数。即数组a的元素是指向函数的指针。
指向的是什么类型的函数?这很明显,是入参为int、返回值为char的类型的函数。
至此解析完毕。
按上述方法,再复杂的也可以一步步解析出来。
就像习武不是为了打人而是为了防身一样,我们了解上述方法是为了看懂别人写的复杂声明,而不是为了在实践中自己去构造这种复杂的东东。实在需要复杂声明时,可以用typedef替代一部分。例如上面语句可改成两句:
typedef char (*FUN_PTR)(int);
FUN_PTR a[3];
这样就清晰多了。
此外,上面的分析方法还让我们对某些东西的本质更加清楚。比如,n维数组的本质都是一维数组。看个具体的例子:
int a[3][5];
这句声明的是一个包含3个元素的一维数组,其每个元素又是一个由5个int数构成的数组。我们不能理解为:a是一个包含5个元素的一维数组,其每个元素又是一个由3个int数构成的数组。为什么?还是按上面的方法分析,这里从略。
有的书上或网上提供"向右看,向左看"的方法, 其实缺乏通用性, 比如它不适用于对多维数组本质的分析. 而且这种方法掩盖了本质. 本质应该是按上面所讲的,根据运算符优先级逐层剥开.
参考:
http://zhidao.baidu.com/question/87026930.html
     // 扩展3 指向成员函数的函数指针
三)在C++类中使用函数指针。
//形式3:typedef 返回类型(类名::*新类型)(参数表)
class CA
{
public:
    char lcFun(int a){ return; }
};
CA ca;
typedef char (CA::*PTRFUN)(int);
PTRFUN pFun;
void main()
{
    pFun = CA::lcFun;
    ca.(*pFun)(2);
}
        在这里,指针的定义与使用都加上了“类限制”或“对象”,用来指明指针指向的函数是哪个类的,这里的类对象也可以是使用new得到的。比如:
CA *pca = new CA;
pca->(*pFun)(2);
delete pca;
        而且这个类对象指针可以是类内部成员变量,你甚至可以使用this指针。比如:
        类CA有成员变量PTRFUN m_pfun;
void CA::lcFun2()
{
   (this->*m_pFun)(2);
}
        一句话,使用类成员函数指针必须有“->*”或“.*”的调用。
6:
struct foo
{
 foo(){};
 void fun(){};
};
下列语句对不对
 foo f;
 f.fun();
 
 foo f2();   // --------------->错误! 无参数的构造函数 不可以使用()号 直接 写变量名字即可!
 f2.fun();
 
7:关于字节对齐
(强调!!!结构体自身也要对其,默认按照其对大元素的对齐值对齐!!!)
假设vc默认8字节对齐
#pragma pack(8)
typedef struct C{
 double a;
 short c;
 int d;
 char b;
};
sizeof(C) = 24;
分析:按照数据类型自身的对齐,应该是20。 然后结构体本身也要有自己的对齐,按照结构体内成员最大的对齐方式对其,也就是double的8字节对齐,所以就是24
同样结构体,如果加上
#pragma pack(4)
....
#pragma pack() // 取消指定对齐
那么sizeof(C) = 20; 因为指定了4字节对齐,结构体也按照4字节对齐。
再来个例子,做对了,就理解了
#pragma pack(8)
typedef struct C{
double* c;
    int a;
char d;
};
sizeof(C) = 12; 结构体内最大的字节对齐为4,所以,结构体本身也按4字节对齐。
理论在于:
1)数据类型自身的对齐值:就是上面交代的基本数据类型的自身对齐值。
2)指定对齐值:#pragma pack (value)时的指定对齐值value。
3)结构体或者类的自身对齐值:其成员中自身对齐值最大的那个值。
4)数据成员、结构体和类的有效对齐值:自身对齐值和指定对齐值中较小的那个值。
char型数据,其自身对齐值为1,对于short型为2,对于int,float,为4, 对于double类型,为8,单位字节
7(腾讯笔试题): 关于 += 和 ++
    int i=1;
    i+=++i+(i++);
    cout<    分析, 从右向左, 表达式右侧为 3 + 1;  此时 i=3, 所以 3+=4 =》 7
8:(深信服笔试题)

下列算符的优先级  %   &   .  &&   <=  =
优先级顺序为(由高到底):.  &    %   <=   &&    =

9:^ 是与或符! 不是指数运算符!搞matlab搞多了 就会把当成指数算符了。 :(
10:fun((exp1, exp2), (exp3, exp4, exp4)) 问该函数共几个参数?
答案,2个,分别是 exp2和exp4, exp1,exp3,exp4也并非无用,是先执行exp1,才执行exp2.
‘,’号是个运算符,自左向右运算。常用语循环语句。eg:
for(  i=1, j=1; ....; .... )
10:分析如下输出
struct C180 {
 C180() {
  foo();
  this->foo();
 }
 void virtual foo() {
  cout << "<< C180.foo this: " << this
   << " vtadr: " << *(void**)this
   << endl;
 }
};
struct C190 : public C180 {
 C190() {}
 void virtual foo() {
  cout << "<< C190.foo this: " << this
   << " vtadr: " << *(void**)this
   << endl;
 }
};
main()
{
    C190 c190;
}
// 输出为
C180.foo this: ***** vtadr:*****
C180.foo this: ***** vtadr:*****
分析 C180的构造函数里第二个foo是通过this指针调用的,为何没有多态输出C190呢? 答案是因为在构造函数执行的时候是不允许多态的。至于为何,见如下文字分析
http://blog.csdn.net/zdl1016/archive/2007/04/15/1565328.aspx
11下面的代码有什么问题?(百度2010)
cin>>num;
int *pInt = int[num];
答案:
cin没有检查返回值。应该:
cin>>num;
if(!cin.fail())
{    int *pInt = int[num];   }
通常来说,以下情况,会导致failbit置位,从而使得cin.fail()返回值为真
1。未能读取到预期的字符,例如int a; cin >> a; 的时候输入了字符
2。I/O失败,例如试图访问不可访问的文件或写入受保护的磁盘、文件。
3。读取到文件尾,即读取文件结尾标志EOF,这时cin.fail()和cin.eof()的返回值都将为真。
12 关于大小端
 在小端机器上(eg:x86),下面代码的输出:
view plaincopy to clipboardprint?
01.void print_px( unsigned char* px )  
02.{  
03. int a = (int)(*px);  
04. cout<< a <05.}  
06.void main()  
07.{   
08. int x = 0x04030201;  
09. unsigned char* px = (unsigned char*)&x;  
10. print_px(px++);  
11. print_px(px++);  
12. print_px(px++);  
13. print_px(px++);  
14.} 
void print_px( unsigned char* px )
{
 int a = (int)(*px);
 cout<< a <}
void main()
{
 int x = 0x04030201;
 unsigned char* px = (unsigned char*)&x;
 print_px(px++);
 print_px(px++);
 print_px(px++);
 print_px(px++);
}
 
答案:在小端机器(eg:pc机x86)上输出 1 2 3 4
         在大端机器(eg:keil c)     上输出 4 3 2 1
这里给出一个将一个buff数据转换大小端转换的例子。注意,是4个字节作为一块转换的,分别把每4个字节全部逆序。
view plaincopy to clipboardprint?
01.inline void McuManager::_ReverseDword(u8 *pucHex, u16 usLen)  
02.{  
03.    //字节序转换  
04.    u8 ucTmp;  
05.    for (int i=0; i06.    {  
07.        //byte3 & 0  
08.        ucTmp = pucHex[i + 0];  
09.        pucHex[i + 0] = pucHex[i + 3];  
10.        pucHex[i + 3] = ucTmp;  
11. 
12.        //byte2 & 1  
13.        ucTmp = pucHex[i + 1];  
14.        pucHex[i + 1] = pucHex[i + 2];  
15.        pucHex[i + 2] = ucTmp;  
16.    }  
17.}

 
阅读(685) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~
评论热议
请登录后评论。

登录 注册