zoukankan      html  css  js  c++  java
  • 面试总结(YY一面)

    YY(欢聚时代)bingo部门

    (一面   2017-03-23下午四点)

    面试官语气挺好的,只不过上来就是问问题。开始之前先问了我能够实习多长时间(我说到九月),以及为什么选择windows程序开发以及后台开发(我说只做过这个啊)。

    首先是问了我一个字节对齐的问题,类中有一个字符和一个整型,问类的大小是多少(这时,我问他系统是32还是64,以及有没有明确要求按几字节对齐),如果类中什么也没没有呢?

    这类问题注意一下几点:

    (1.类的大小为类的非静态成员数据的类型大小之和,也 就是说静态成员数据不作考虑。

    (2.普通成员函数与sizeof无关。

    (3.虚函数由于要维护在虚函数表,所以要占据一个指针大小,也就是4字节。

    (4.类的总大小也遵守类似class字节对齐的,调整规则。

    (5.因为一个空类也要实例化,所谓类的实例化就是在内存中分配一块地址,每个实例在内存中都有独一无二的地址。同样空类也会被实例化,所以编译器会给空类隐含 的添加一个字节,这样空类实例化之后就有了独一无二的地址了。所以空类的sizeof为1。

    第二个问题是排序,你知道的排序有哪些,plusplusplus,说了一通,然后面试官说那你给我说说快排的大致过程是怎样的吧,我说了后他又问怎么优化呢,我说从标志位的选择上,随机的方法应该好一些;

    快排的优化:http://blog.csdn.net/wangjin123456789/article/details/50772220

    第三个问题是:给你一个字符串如何找出第一次只出现一次的字符;

    接下来是网络的部分:

    一个HTTP的完整流程

    (1.打开HTTP连接。因为HTTP是一种无状态协议,所以每个请求都需要建立一个新连接。

    (2.初始化方法请求。包含一些类型的方法提示符,它们用来描述调用什么方法和需要什么参数。

    (3.设置HTTP请求头。包含要传输的数据类型和数据长度。

    (4.发送请求。即将二进制流写入服务器。

    (5.读取请求。调用目标servlet程序,并接受HTTP请求数据。如果该次请求为客户端第一次请求,则需要建立一个新的服务器对象实例。

    (6.调用方法。提高服务器端调用对象的方法。

    (7.初始化响应方法。如果调用的方法出现异常,客户将会收到出错信息;否则,发送返回类型。

    (8.设置HTTP响应头。响应头中设置待发送的数据类型和长度。

    (9.发送响应。服务器端发送二进制数据流给客户端作为响应。

    (10.关闭连接。当响应结束后,与服务器必须断开连接,以保证其他请求能够与服务器建立连接。

    DNS:

    那么我们的DNS是怎么解析一个域名的呢?

    1.现在我有一台计算机,通过ISP接入了互联网,那么ISP就会给我分配一个DNS服务器,这个DNS服务器不是权威服务器,而是相当于一个代理的dns解析服务器,他会帮你迭代权威服务器返回的应答,然后把最终查到IP返回给你。

    2.现在的我计算机要向这台ISPDNS发起请求查询www.baidu.com这个域名了,(经网友提醒:这里其实准确来说不是ISPDNS,而应该是用户自己电脑网络设置里的DNS,并不一定是ISPDNS。比如也有可能你手工设置了8.8.8.8)

    3.ISPDNS拿到请求后,先检查一下自己的缓存中有没有这个地址,有的话就直接返回。这个时候拿到的ip地址,会被标记为非权威服务器的应答

    4.如果缓存中没有的话,ISPDNS会从配置文件里面读取13个根域名服务器的地址(这些地址是不变的,直接在BIND的配置文件中),

    5.然后像其中一台发起请求。

    6.根服务器拿到这个请求后,知道他是com.这个顶级域名下的,所以就会返回com域中的NS记录,一般来说是13台主机名和IP。

    7.然后ISPDNS向其中一台再次发起请求,com域的服务器发现你这请求是baidu.com这个域的,我一查发现了这个域的NS,那我就返回给你,你再去查。

    (目前百度有4台baidu.com的顶级域名服务器)。

    8.ISPDNS不厌其烦的再次向baidu.com这个域的权威服务器发起请求,baidu.com收到之后,查了下有www的这台主机,就把这个IP返回给你了,

    9.然后ISPDNS拿到了之后,将其返回给了客户端,并且把这个保存在高速缓存中。

    然后问我会编译原理吗,我说大学的时候学了,不过都忘的差不多了。

    然后问我const修饰指针时放的位置不同有什么差异,如果在前面再加一个static呢?staic int *p2; /*p2是指向静态整型变量的指针变量

    还问了函数指针的原理:

       定义

    每一个函数都占用一段内存单元,它们有一个起始地址,指向函数入口地址的指针称为函数指针。

       语法

    指向函数的指针变量的一般定义形式为:

    数据类型 (*指针变量名)(参数表);

       说明

    1) 函数指针的定义形式中的数据类型是指函数的返回值的类型。

    2) 区分下面两个语句:

    int (*p)(int a, int b); //p是一个指向函数的指针变量,所指函数的返回值类型为整型

    int *p(int a, int b); //p是函数名,此函数的返回值类型为整型指针

    3) 指向函数的指针变量不是固定指向哪一个函数的,而只是表示定义了一个这样类型的变量,它是专门用来存放函数的入口地址的;在程序中把哪一个函数的地址赋给它,它就指向哪一个函数。

    4) 在给函数指针变量赋值时,只需给出函数名,而不必给出参数。

    如函数max的原型为:int max(int x, int y); 指针p的定义为:int (*p)(int a, int b); 则p = max;的作用是将函数max的入口地址赋给指针变量p。这时,p就是指向函数max的指针变量,也就是p和max都指向函数的开头。

    5) 在一个程序中,指针变量p可以先后指向不同的函数,但一个函数不能赋给一个不一致的函数指针(即不能让一个函数指针指向与其类型不一致的函数)。

    如有如下的函数:int fn1(int x, int y); int fn2(int x);

    定义如下的函数指针:int (*p1)(int a, int b); int (*p2)(int a);

    p1 = fn1; //正确

    p2 = fn2; //正确

    p1 = fn2; //产生编译错误

    6) 定义了一个函数指针并让它指向了一个函数后,对函数的调用可以通过函数名调用,也可以通过函数指针调用(即用指向函数的指针变量调用)。

    如语句:c = (*p)(a, b); //表示调用由p指向的函数(max),实参为a,b,函数调用结束后得到的函数值赋给c。

    7) 函数指针只能指向函数的入口处,而不可能指向函数中间的某一条指令。不能用*(p+1)来表示函数的下一条指令。

    8) 函数指针变量常用的用途之一是把指针作为参数传递到其他函数。

    妙用函数指针一: 函数指针数组

    [cpp] view plain copy
     
    1. <span style="font-size:16px;">void main()  
    2. {  
    3.     int i;  
    4.     void (*p[])()={Touch,DuanJiong,MeiKai,YinJun,JiangHaiLong};  
    5.     scanf("%d",&i);  
    6.     p[i]();  
    7. }  
    8. </span>  

    void (*p[])()={Touch,DuanJiong,MeiKai,YinJun,JiangHaiLong};声明了一个函数指针数组并赋值。把每个函数的入口地址存入这个数组,这样就不需要用switch语句了,根据下标i直接找到函数入口,省去了判断的时间。

    妙用函数指针二: 回调函数

    什么是回调函数,来着百度百科的解释:回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用为调用它所指向的函数时,我们就说这是回调函数。这里函数指针是作为参数传递给另一个函数。

    1. <span style="font-size:16px;">//回调函数对多种数据类型数组进行冒泡排序  
    2. //a表示待排序数组  
    3. //n表示数组长度  
    4. //size表示数组元素大小(即每个数组元素占用的字节数)  
    5. //int (*compare)(void *,void *) 声明了一个函数指针,在此作为参数  
    6. //void *类型的指针表示指向未知类型的指针,编译器并不会给void类型的指针分配空间,但我们可以把它进行强制类型转换  
    7. void bubbleSort(void *a,int n,int size,int (*compare)(void *,void *))  
    8. {  
    9.     int i,j,k;  
    10.     char *p,*q;  
    11.     char temp;//交换时暂存一个字节的数据  
    12.     for(i=0;i<n;i++)  
    13.         for(j=0;j<n-i-1;j++){  
    14.             //注意p,q都是字符类型的指针,加一都只移动一个字节  
    15.             </span><span style="font-size:16px;"><span style="color:#cc0000;">p=(char*)a+j*size;  
    16. </span>         </span><span style="font-size:16px;"><span style="color:#cc0000;">q=(char*)a+(j+1)*size;  
    17. </span>         if(compare(p,q)>0){  
    18.                 //一个一个字节的交换,从而实现了一个数据类型数据的交换  
    19.                 for(k=0;k<size;k++){  
    20.                     temp=*p;  
    21.                     *p=*q;  
    22.                     *q=temp;  
    23.                     </span><span style="font-size:16px;"><span style="color:#cc0000;">p++;  
    24. </span>                 </span><span style="font-size:16px;"><span style="color:#cc0000;">q++;  
    25. </span>             }  
    26.             }  
    27.         }  
    28. }</span>  

    请注意代码中红色部分代码,要看懂这段代码需明确两个问题:(1)void*类型的指针未分配空间的,我们可以把它进行强制类型转换成char*。(2)对数组元素进行交换时,并不是一次就把两个数交换了,因为我们并不知道数据的确切类型。但知道数组元素的大小,这样就可以逐个字节进行交换。比如对int类型(占用四个字节)的值a、b进行交换,先交换a、b的第一个字节,然后第二个字节...

    理解了这个代码,该怎么用呢?参数要传入一个函数指针,于是必须要写一个比较两个数大小的函数,且函数原型必须与int (*compare)(void *,void *)相匹配。下面是测试各种类型数组排序的代码:

    [cpp] view plain copy
     
    1. <span style="font-size:16px;">#include<stdio.h>  
    2.   
    3. typedef struct{  
    4.     int data;  
    5. }Node;  
    6.   
    7. //函数声明  
    8. int charCompare(void *a,void *b);  
    9. int intCompare(void *a,void *b);  
    10. int floatCompare(void *a,void *b);  
    11. int doubleCompare(void *a,void *b);  
    12. int nodeCompare(void *a,void *b);  
    13. void bubbleSort(void *a,int n,int size,int (*compare)(void *,void *));  
    14.   
    15. //比较两个char类型的数据的大小,a>b返回1,a<b返回-1,a==b返回0  
    16. int charCompare(void *a,void *b)  
    17. {  
    18.     if(*(char*)a==*(char*)b)  
    19.         return 0;  
    20.     return *(char*)a>*(char*)b?1:-1;  
    21. }  
    22. //比较两个int类型的数据的大小  
    23. int intCompare(void *a,void *b)  
    24. {  
    25.     if(*(int*)a==*(int*)b)  
    26.         return 0;  
    27.     return *(int*)a>*(int*)b?1:-1;  
    28. }  
    29. //比较两个float类型的数据的大小  
    30. int floatCompare(void *a,void *b)  
    31. {  
    32.     if(*(float*)a==*(float*)b)  
    33.         return 0;  
    34.     return *(float*)a>*(float*)b?1:-1;  
    35. }  
    36. //比较两个double类型的数据的大小  
    37. int doubleCompare(void *a,void *b)  
    38. {  
    39.     if(*(double*)a==*(double*)b)  
    40.         return 0;  
    41.     return *(double*)a>*(double*)b?1:-1;  
    42. }  
    43. //比较两个结构体类型(Node)的数据的大小  
    44. int nodeCompare(void *a,void *b)  
    45. {  
    46.     if(((Node*)a)->data == ((Node*)b)->data)  
    47.         return 0;  
    48.     return ((Node*)a)->data > ((Node*)b)->data ? 1 : -1;  
    49. }  
    50.   
    51. void main()  
    52. {  
    53.     int i=0;  
    54.     //用于测试的各种类型数组  
    55.     char c[]={'d','a','c','e','b'};  
    56.     int a[]={3,2,4,0,1};  
    57.     float f[]={4.4,5.5,3.3,0,1};  
    58.     double b[]={4.4,5.5,3.3,0,1};  
    59.     Node n[]={{2},{0},{1},{4},{3}};  
    60.   
    61.     //对各种数组进行排序  
    62.     puts("对char类型数组进行排序:");  
    63.     bubbleSort(c,5,sizeof(char),charCompare);  
    64.     for(i=0;i<5;i++)  
    65.         printf("%c ",c[i]);  
    66.     puts("");  
    67.   
    68.     puts("对int类型数组进行排序:");  
    69.     bubbleSort(a,5,sizeof(int),intCompare);  
    70.     for(i=0;i<5;i++)  
    71.         printf("%d ",a[i]);  
    72.     puts("");  
    73.   
    74.     puts("对float类型数组进行排序:");  
    75.     bubbleSort(f,5,sizeof(float),floatCompare);  
    76.     for(i=0;i<5;i++)  
    77.         printf("%.2f ",f[i]);  
    78.     puts("");  
    79.   
    80.     puts("对double类型数组进行排序:");  
    81.     bubbleSort(b,5,sizeof(double),doubleCompare);  
    82.     for(i=0;i<5;i++)  
    83.         printf("%.2lf ",b[i]);  
    84.     puts("");  
    85.   
    86.     puts("对结构体(Node)类型数组进行排序:");  
    87.     bubbleSort(n,5,sizeof(Node),nodeCompare);  
    88.     for(i=0;i<5;i++)  
    89.         printf("%d ",n[i].data);  
    90.     puts("");  
    91. }  
    92.   
    93.   
    94. //回调函数对多种数据类型数组进行冒泡排序  
    95. //a表示待排序数组  
    96. //n表示数组长度  
    97. //size表示数组元素大小(即每个数组元素占用的字节数)  
    98. //int (*compare)(void *,void *) 声明了一个函数指针,在此作为参数  
    99. //void *类型的指针表示指向未知类型的指针,编译器并不会给void类型的指针分配空间,但我们可以把它进行强制类型转换  
    100. void bubbleSort(void *a,int n,int size,int (*compare)(void *,void *))  
    101. {  
    102.     int i,j,k;  
    103.     char *p,*q;  
    104.     char temp;//交换时暂存一个字节的数据  
    105.     for(i=0;i<n;i++)  
    106.         for(j=0;j<n-i-1;j++){  
    107.             //注意p,q都是字符类型的指针,加一都只移动一个字节  
    108.             p=(char*)a+j*size;  
    109.             q=(char*)a+(j+1)*size;  
    110.             if(compare(p,q)>0){  
    111.                 //一个一个字节的交换,从而实现了一个数据类型数据的交换  
    112.                 for(k=0;k<size;k++){  
    113.                     temp=*p;  
    114.                     *p=*q;  
    115.                     *q=temp;  
    116.                     p++;  
    117.                     q++;  
    118.                 }  
    119.             }  
    120.         }  
    121. }</span>

    类的静态成员函数和实例函数有什么区别,在什么时候创建的?静态成员和非静态成员?

    (1)所有的函数都是存放在代码区的,不管是全局函数,还是成员函数。要是成员函数占用类的对象空间,那么将是多么可怕的事情:定义一次类对象就有成员函数占用一段空间。 我们再来补充一下静态成员函数的存放问题吧:静态成员函数与一般成员函数的唯一区别就是没有this指针,因此不能访问非静态数据成员,就像我前面提到的,所有函数都存放在代码区,静态函数也不例外。所有有人一看到 static 这个单词就主观的认为是存放在全局数据区,那是不对的

    (2)类中的静态成员变量是类的所有对象都共用的成员变量。分配在内存中的数据区。
    要用“类名+静态变量名”来访问。
    不管new多少个对象都共用这个固定的变量,即使不new对象,也会存在于数据区内,也可以使用。

    静态变量存储在静态存储区,程序启动时就分配空间,程序退出时释放。
    普通成员变量在类实例化时分配空间,释放类的时候释放空间,存储在栈或堆中。
  • 相关阅读:
    单利设计模式
    Jquery中的ajax应用(第九章PPT)
    求Sn=a+aa+aaa+aaaa+aaaaa的前5项之和,其中a是一个数字
    求出0~999之间的所有“水仙花数”并输出
    输出三角和倒三角
    编写程序数一下 1到 100 的所有整数中出现多少次数字9(对整数每一位的提取方法)
    计算1/1-1/2+1/3-1/4+1/5 …… + 1/99
    将数组A中的内容和数组B中的内容进行交换。(数组一样大)
    求两个数的最大公约数(列举法与辗转相除法)
    将三个数从大到小输出
  • 原文地址:https://www.cnblogs.com/believe-in-me/p/6607208.html
Copyright © 2011-2022 走看看