一、四层网络模型与七层网络模型(每层写出对应的三个协议)?
七层网络模型:应用层 表示层 会话层 传输层 网际层 数据链接层 物理层
四层网络模型:
应用层:TFTP、FTP、Telnet、DNS
传输层:TCP、UDP
网际层:ICMP、IP、ARP、RARP
网络接口层:FDDI、PDN、PPP、IEEE802.1A(各种通信网络接口)
二、用两个栈实现一个队列的功能?要求给出算法和思路?
思路:入队:将元素进栈 A
出队:判断栈 B 是否为空,如果为空,则将栈 A 中所有元素 pop,并 push 进栈 B,栈 B 出栈;
如果不为空,栈 B 直接出栈
算法:
class Solution
{
public:
void push(int node)
{
stack1.push(node);
}
int pop()
{
if (stack2.empty())
{
while (!stack1.empty())
{
stack2.push(stack1.top());
stack1.pop();
}
}
int a = stack2.top();
stack2.pop();
return a;
}
private:
stack<int> stack1;
stack<int> stack2;
};
说到这了,那用两个队列实现一个栈呢
思路:队列是先进先出,所以要拿到队列中最后压入的元素,只能每次将队列中元素 pop 到只剩一个,
此时这个元素为最后压入队的元素,循环往复
算法:
class CStack //两个队实现一个栈
{
public:
void push(int node)
{
if (!q1.empty())
{
q1.push(node);
}
else
{
q2.push(node);
}
}
int deleteHead()
{
int ret = 0;
if (q1.empty())
{
int i = q2.size();
while (i > 1)
{
q1.push(q2.front());
q2.pop();
--i;
}
ret = q2.front();
q2.pop();
}
else
{
int i = q1.size();
while (i > 1)
{
q2.push(q1.front());
q1.pop();
--i;
}
ret = q1.front();
q1.pop();
}
return ret;
}
private:
queue<int> q1;
queue<int> q2;
};
三、论述含参数的宏和函数的优缺点?
1、函数调用时,先求出实参表达式的值,然后带入形参。而使用带参的宏只是进行简单的字符替换
2、函数调用是在程序运行时处理的,分配临时的内存单元;而宏展开则是在编译时进行的,在展开
时并不分配内存单元,不进行值得传递处理,也没有返回值的概念
3、对函数中的实参和形参都要定义类型,二者的类型要一致,如不一致,应进行类型转换;而宏不
存在这样的问题,宏名无类型,它的参数也无类型,只是一个符号代表,展开时带入指定的字符即可
宏定义时,字符串可以是任何类型的数据
4、调用函数只可得到一个返回值,而用宏可以设法得到几个结果
5、使用宏次数多时,宏展开后源程序长,因为每次展开都会使程序增长,而函数调用不会使程序增长
6、宏替换不占用运行时间、只占编译时间;而函数调用则占运行时间
一般来说,用宏来代表简短的表达式比较合适
四、结构与联合有何区别?
1、在存储多个成员信息时,编译器会自动给 struct 每个成员分配存储空间,struct 可以存储多个成员信息
而 union 每个成员会用同一个存储空间,只能存储最后一个成员的信息
2、都是由多个不同数据类型成员组成,但在任何同一时刻,Union 只存放了一个被先选中的成员,而结构体
的所有成员都存在
3、对于 Union 的不同成员赋值,将会对其他成员重写,原来成员的值就不存在了,而对于 struct 的不同成员
赋值是互不影响的
五、引用与指针有什么区别?
1、初始化要求不同。引用在创建的同时必须初始化,即引用到一个有效的对象;而指针在定义的时候不必初始化
可以在定义后面的任何地方重新赋值
2、可修改性不同。引用一旦被初始化为一个对象,它就不能被改变为另一个对象的引用;而指针在任何时候都可以
改变为指向另一个对象。给引用赋值并不是改变它和原始对象的绑定关系
3、不存在 NULL 引用,引用不能使用指向空值的引用,它必须指向某个对象;而指针则可以是NULL,可以把指针
指向任意的对象,所以指针更加灵活
4、使用引用之前不需要测试它;而指针需要经常测试;因此使用引用的效率比指针高
5、如果是一旦指向一个对象后就不会改变指向,那么应该使用引用,如果存在指向 NULL 或在不同时刻指向不同
的对象这些可能性,应该使用指针
六、C++建议用 const 来代替宏常量
1、const 常量是在编译的时候进行处理,会做类型检查
宏常量不会做类型检查,在预处理期间进行完全替换
2、C++ const 修饰的是一个常量,常量的值会放到符号表中去,如果对 const 修饰的变量进行取地址操作,则编译器
会在内存中为这个变量分配空间,但这个空间不使用
3、宏常量不会做作用域检查,const 常量会;宏常量的作用域定义的位置开始到文件结束
宏是可以撤销的
七、TCP三次握手和四次挥手
TCP 是主机对主机层的传输控制协议,提供可靠的连接服务,采用三次握手确认建立一个连接
tcp 标志位
SYN 建立连接
ACK 表示响应、确认
PSH 表示 DATA 数据传输
FIN 关闭连接
RST 表示连接重置
URG 紧急指针字段值有效
三次握手:
第一次握手:客户端发送 syn 包到服务器,并确认进入 SYN_SEND状态,等待服务器确认
第二次握手:服务器收到 syn 包,必须确认客户的 SYN ,同时自己发送一个 SYN 包,即 SYN+ACK包,此时服务器进入 SYN_RECV状态
第三次握手:客户端收到服务器的 SYN+ACK包,向服务器发送确认包 ACK ,此包发送完毕,完成三次握手
四次挥手:
第一次挥手:客户端发送一个 FIN 包,请求关闭连接
第二次挥手:服务器收到 FIN 包,发送一个 ACK 给客户端,
第三次挥手:服务器发送给客户端一个 FIN ,结束该报文段
第四次挥手:客户端收到 FIN 后,发送一个 ACK 给服务器,确认该结束报文段