写在开头,首先面试要保持好良好的心态,不要过于自信,也不要过于自负。当面试官问问题时,要仔细听,如果不确定自己理解的意思是否符合面试官的想法,可以将自己的想法告知ta,问问可不可这样理解。如果问到一时间想不到答案的问题,可以谈谈自己的看法(千万不要说自己不会,自己看情况决定)。回答问题时,要清除的表达自己的答案。

好吧!这次的面试经过了1个小时,写一篇博客记录一下。希望能有第二次面试,得到一个进大厂的机会。人生之长,我在慢慢走!

最后,给看者一个建议:小伙子,不要怂,就是干!你都怂了,肯定不能发挥好,要自信,当然,不能过度自信,不然就是吹,就是自负了!

【博客大赛】腾讯一面(客户端开发)_C++

面试官:介绍一下你的开发经历。

我:大一使用C语言开发带有GUI界面2048游戏;大二使用Java开发过一个类似跑酷的游戏,在此期间也有过一个使用C#开发的项目;大三有过JavaWeb的开发;目前也有些项目在进行中。

面试官:2048那个游戏是怎么实现的(只记得大概意思了)

我:使用开源的Easy-X库函数实现的。

面试官:以下的代码有没有什么问题,如果有问题进行修改(代码如下)

void fun(){
    char string[10];
    char* str = "0123456789";
    strcpy(string,str1);
}

我:没有使用的错误,在输出方面存在问题。(要注意区别指针和数组的区别,我修改的代码如下)

#include int main(){
    char string[10];
    char* str = "0123456789";
    
    for(int i=0;I<10;i++){
        string[i] = *(str + i);
    }
    
    printf("%s",string);
    
    return 0;
}

面试官:指针和数组有什么区别。

我:(使用不多,先前学的也不大记得了)当时也就说了内存空间的使用问题。

具体参考如下:

1.指针变量用于保存数据的地址,数组用于直接保存数据(当然你可能见过,数组的每个元素是指针,不过,一组指针也是数据,它们各自的内容才是地址)。

2.访问方式:指针是间接访问,首先取得指针的内容作为地址,再去该地址访问数据;数组是直接访问,数组名即是地址。

3.指针通常用于动态数据;数组通常用于固定数目和类型的一组数据。

4.定义指针变量并不会带来内存分配,要自行分配内存并且将指针变量的内容改写为分配好的地址,通常用内存分配函数如malloc达到;定义数组会隐式分配内存。

5.对sizeof操作符的返回值影响,sizeof(指针)永远会返回平台指针大小,通常32位机返回4,64位返回8,而sizeof(数组名),则会返回数组的内存大小,这取决于数组包含多少个数据。

面试官:野指针是怎么出现的?会造成什么影响?如何避免?

我:指针用的不多,在实际开发中也不敢用,我说一说我的理解(.……记不大清了,说道了作用域,又扯了些数据交换)

具体参考如下:

    野指针的产生有以下3种情况:

1、定义一个指针变量时没有初始化

2、动态开辟的内存空间在使用完后调用free函数释放掉这段内存空间,

3、对指针的操作已经超出了指针变量的作用域

    使用野指针会产生的后果 ,这里分为3种情况:

1、指向不可访问的地址 

危害:触发段错误。 

2、指向一个可用的,但是没有明确意义的空间 

危害:程序可以正确运行,但通常这种情况下,我们就会认为我们的程序是正确的没有问题的,然而事实上就是有问题存在,所以这样就掩盖了我们程序上的错误。 

3、指向一个可用的,而且正在被使用的空间 

危害:如果我们对这样一个指针进行解引用,对其所指向的空间内容进行了修改,但是实际上这块空间正在被使用,那么这个时候变量的内容突然被改变,当然就会对程序的运行产生影响,因为我们所使用的变量已经不是我们所想要使用的那个值了。通常这样的程序都会崩溃,或者数据被损坏。

    如何避免 :

1、定义一个指针变量时一定记得初始化 
2、动态开辟的内存空间使用完free之后一定将对应的指针置为NULL 
3、不要在函数中返回栈空间的指针和引用 
4、注意在使用时对指针的合法性的判断

面试官:当有两个进程访问一块内容时会出现什么问题?怎么解决?(详细问法不大记得了,要问的是死锁的问题)

我:可能会出现死锁。当一个进程访问文件时,给当前被访问的文件加锁,在访问结束后再进行解锁,给其他进程访问该文件的权限。(答的不全面)

参考链接

面试官:说一下TCP的三次握手和四次挥手

参加了三次面试都有问过,也算是个常见的问题。

具体参考如下:

    三次握手过程理解

第一次握手:建立连接时,客户端发送syn包(syn=j)到服务器,并进入SYN_SENT状态,等待服务器确认;SYN:同步序列编号(Synchronize Sequence Numbers)。

第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态;

第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED(TCP连接成功)状态,完成三次握手。

    四次挥手过程理解 

1)客户端进程发出连接释放报文,并且停止发送数据。释放数据报文首部,FIN=1,其序列号为seq=u(等于前面已经传送过来的数据的最后一个字节的序号加1,此时,客户端进入FIN-WAIT-1(终止等待1)状态。 TCP规定,FIN报文段即使不携带数据,也要消耗一个序号。

2)服务器收到连接释放报文,发出确认报文,ACK=1,ack=u+1,并且带上自己的序列号seq=v,此时,服务端就进入了CLOSE-WAIT(关闭等待)状态。TCP服务器通知高层的应用进程,客户端向服务器的方向就释放了,这时候处于半关闭状态,即客户端已经没有数据要发送了,但是服务器若发送数据,客户端依然要接受。这个状态还要持续一段时间,也就是整个CLOSE-WAIT状态持续的时间。

3)客户端收到服务器的确认请求后,此时,客户端就进入FIN-WAIT-2(终止等待2)状态,等待服务器发送连接释放报文(在这之前还需要接受服务器发送的最后的数据)。

4)服务器将最后的数据发送完毕后,就向客户端发送连接释放报文,FIN=1,ack=u+1,由于在半关闭状态,服务器很可能又发送了一些数据,假定此时的序列号为seq=w,此时,服务器就进入了LAST-ACK(最后确认)状态,等待客户端的确认。

5)客户端收到服务器的连接释放报文后,必须发出确认,ACK=1,ack=w+1,而自己的序列号是seq=u+1,此时,客户端就进入了TIME-WAIT(时间等待)状态。注意此时TCP连接还没有释放,必须经过2∗∗MSL(最长报文段寿命)的时间后,当客户端撤销相应的TCB后,才进入CLOSED状态。

6)服务器只要收到了客户端发出的确认,立即进入CLOSED状态。同样,撤销TCB后,就结束了这次的TCP连接。可以看到,服务器结束TCP连接的时间要比客户端早一些。

博文推荐:

面试官,求你了别再问我TCP三次握手和四次挥手了(含面试题)

TCP的三次握手与四次挥手理解及面试题(很全面)

面试官:TCP和UDP有什么区别

我:在用户实际的使用过程中是感觉不到特别大的区别。在实际传输过程中TCP是可靠的连接,它要保证数据能够到达接收方,因此需要消耗一定的资源,而UDP仅仅只是发送数据,相比TCP的消耗要小一些(其他的忘记了说)

具体参考如下:

  1.基于连接与无连接

  2.TCP要求系统资源较多,UDP较少; 

  3.UDP程序结构较简单 

  4.流模式(TCP)与数据报模式(UDP); 

  5.TCP保证数据正确性,UDP可能丢包 

  6.TCP保证数据顺序,UDP不保证 

博文参考:

    TCP和UDP的最完整的区别

    面试题:TCP协议与UDP协议的区别

面试官:一个视频通话需要什么连接

我:这需要基于用户使用量进行选择,如果用户数量少,可以优先考虑TCP;当使用量过高时,可以优先考虑UDP。综合来看应当将TCP和UDP结合使用。

面试官:SQL注入***是怎么引起的?有哪些具体的分类?

我:一般是由工程师没有严格控制用户输入的数据造成的,即工程师没有秉持“外部参数皆不可信的原则”。(具体的分类不记得了,就说具体的分类不大了解)

具体的参考如下:

    SQL注入

SQL注入就是指Web应用程序对用户输入数据的合法性没有判断,前段传入后端的参数是***者可控的,并且参数带入数据库查询,***者可以通过构造不同的SQL语句来实现对数据库的任意操作。

    SQL注入的分类

1、带内(In-band)SQLi,也叫经典SQLi

2、推测SQL注入(盲注)

3、带外SQLi

 博文参考:

    SQL注入的分类

    常见sql注入的类型

面试官:给定一个二叉树,找出路径上其和相等的任意两条路径

#include struct TreeNode {
    struct TreeNode* left;
    struct TreeNode* right;
    int value;
}


int main(){
    struct TreeNode* root = malloc(sizeof(struct TreeNode));
    root->value = 1;

    struct TreeNode* left1 = malloc(sizeof(struct TreeNode));
    left1->value = 2;
    left1->left = NULL;
    left1->right = NULL;

    struct TreeNode* right1 = malloc(sizeof(struct TreeNode));
    right1->value = 3;
    right1->left = NULL;
    right1->right = NULL;

    root->left = left1;
    root->right = right1;
    
    return 0;


}

我:这个编程可能会花一些时间,可以说一下我的想法吗(害,链表实在是接触不多,编程可能真的会好久)(面试官那边也同意了)。可以采用深度或广度优先遍历的方法对这棵树进行遍历。将数据存在结构体数组中(其他的数据结构也可以),结构体中包含一个链表存放路径,另外一个整形变量存放累加和。最后通过比较累加和,输出符合条件的两条路径。

面试官问道了许多有关算法的时间复杂度,一定要会计算。还有些开放性的问题,在这里就不一一阐述了。

还有一道编程,具体要求不记得了,代码如下:

//这是提交后的,自己也不知道对不对,看看就行
#include using namespace std;

struct Test {
    int a;
};

int main() {
    Test a;
    fun(a);
}


void fun(Test a) {

}
写在最后的话

机会遍地都是,但是能不能抓住,就要看你是否做好了准备了。

希望大家都能找到自己心仪的工作,如果通过努力进入了心仪的公司,也不要放松,学习就是逆水行舟,不进则退。


当大潮褪去,你才知道谁在裸泳。


你知道的越多,你不知道的越多,人才们的 【三连】 就是我创作的最大动力,我们下期见!


注:如果本篇博客有任何错误和建议,欢迎人才们留言,你快说句话啊!


原文链接https://blog.xuanzhe.club/?id=41