自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(43)
  • 收藏
  • 关注

转载 简单解释 P2P 技术之 UDP 打洞

P2P 通信最大的障碍就是 NAT(网络地址转换),NAT 使得局域网内的设备也可以与公网进行通讯,但是不同 NAT 下的设备之间通讯将会变得很困难。UDP 打洞就是用来使得设备间绕过 NAT 进行通讯的一种技术。简单解释 NATNAT 大家应该十分熟悉了,它分为几种。一种就叫做 NAT,它只对 IP 地址进行转换;另一种叫做 NAPT(Network Address/Port Translation),它可以对整个会话的端点(由 IP 地址和端口号组成)做转换,这是一种更加常见的 NAT 变种。当然了

2020-08-18 09:48:34 1251

转载 【Gerrit】Gerrit工作流程及使用手册

gerrit的流程、权限控制其实对于初次接触的同学们来说,确实有点复杂。我希望这篇文章过后,我们能对gerrit的流程有一个大致的了解。这篇文章将用一个真实的例子,演示一下gerrit的管理员,普通项目成员是如何协同完成项目管理工作的。这篇文章首先会大致讲解下gerrit的工作流程;然后介绍管理员的相关配置工作,包括设置SSH密钥验证,添加新成员;接下来会用一个示例演示普通成员push一个co...

2020-04-24 17:55:51 9702

原创 \r和\n

关于\r和\n的思考源于处理FTP服务器返回的消息的时候,我知道消息末尾有\n,但是就算比较信息加上\n也不对,于是查了资料就发现原来消息末尾还有\r,然后就又去查了\r与\n,看了一些文章,做一点总结。1、\r和\n的作用\r就是回车,并且回到行首,\n就是换行,如果只有\r在末尾,那么在屏幕上是没有输出的例如: printf("hello\r"); printf("12345\n")...

2020-03-30 14:26:50 15001 2

原创 C语言中的内存分配

1、代码段(text)里面存储的是可执行程序的二进制指令,为了防止被意外修改,代码段一般是只读的2、全局段(数据段data)存储被初始化过的全局变量、静态变量3、bss段(静态数据段)存储静态变量(被static修饰过的变量)和末初始化的全局变量,这段内存在程序运行前会被初始化为04、堆(heap)程序员手动管理,与指针配合使用,足够大,释放时间受控制,但不安全,容易产生内存碎片、内...

2019-10-06 20:40:12 327

原创 深入理解指针

一、什么是指针指针是一种数据类型,是无符号整数,不过这个整数有特殊意义,它代表着内存编号二、为什么要用指针1、函数之间需要共享变量,全局变量虽然也可以,但是不宜过多,可以把变量的地址编号传递给其它函数来达到共享变量的目的2、优化函数之间的传参效率,函数之间采用的是值传递传参,是内存的拷贝,当传的字节数很多时,效率会很低,但是如果只是传递变量的地址只需要传4字节(64位操作系统是8字节)3...

2019-10-06 15:49:44 593

原创 内存泄漏

一、什么是内存泄漏由于内存管理失败导致堆内存忘记释放或者无法释放,导致堆内存无法循环使用的情况叫做内存泄漏注意:当程序结束后所有的资源都会被系统回收,包括泄漏的内存二、内存泄漏的原因1、C语言中malloc/free函数不匹配(忘记写free或者没有执行到free),在C++中类的构造函数和析构函数中没有匹配的调用new和delete函数2、 在释放对象数组时在delete中没有使用方括...

2019-10-06 15:47:55 262

原创 strlen与sizeof的区别

1、strlen是函数,sizeof是运算符2、strlen只能计算字符串的长度,而且要想得到正确的长度,字符串后面必须包含’\0’,sizeof的参数可以是数组、指针、类型、对象、函数等3、在计算字符数组的时候strlen算的是实际有的字符数,而sizeof计算的是数组的大小举个例子:#include <stdio.h>#include <string.h>...

2019-10-06 15:11:00 293

原创 如何判断大小端

一、什么是大小端低位地址存储低位数据的是小端,低位地址存储高位数据的是大端举个例子:假设我定义int num = 0x01020304;,那么0x01是高位数据,0x04是低位数据,我们再假设这个数据存储在0xe1e2e3e4这个地址中那么如果数据是这么存的就是小端:0xe1e2e3e4(低位地址) = 0x040xe1e2e3e5 = 0x030xe1e2e3e6 = 0x02...

2019-10-05 17:15:21 1645

原创 如何写Makefile

一、什么是MakefileMakefile是一种编译脚本,里面记录的编译代码的命令的集合二、为什么要使用Makefile1、随着项目规模的不断增加,代码量越来越来多,为了更好的管理代码、协同工作,不得不把代码拆分、设计成多个文件2、由于源文件过多,编译时命令不易写,编译时间过长,而使用Makefile可以多目录编译,一次编写循环利用,有效节约编译时间3、Makefile中可以使用分支、循...

2019-10-05 16:41:26 262

原创 空指针与野指针

一、什么是空指针指针变量的值等于NULL(#define NULL ((void *)0))的指针叫做空指针注意:空指针不能解引用,因为此地址存储的是系统复位时要使用数据,不能访问,一旦解引用就会出现段错误二、如何避免使用空指针对来历不明的指针前要先判断是否是空指针,if(NULL == p)注意:NULL不一定是0,也有可能是1三、什么是野指针指向的内存不明确的指针叫野指针...

2019-10-05 11:02:32 405

原创 STL模板库中常用的容器

一、C++中容器类型C++中有两种类型的容器:顺序容器和关联容器顺序容器主要有vector、list、deque等关联容器主要有map和set注意:容器类自动申请和释放内存,因此无需new和delete操作二、迭代器类似于专门用来指向容器成员的指针,用来遍历、操作、管理容器中的成员,可以大大提高对容器的访问速度用法:容器类名<>::iterator 迭代器名*迭代器名...

2019-10-04 19:50:04 487

原创 解析宏函数与内联函数

一、宏函数的优点宏函数只是在预处理的地方把代码展开,不需要额外的空间和时间方面的开销,所以调用一个宏比调用一个函数更有效率二、宏函数的缺点宏函数只是简单的文本替换,不会做类型和语法的检查,而且宏函数容易出现二义性三、内联函数的优点提高程序的运行速度(因为没有跳转,也不需要返回)四、内联函数的缺点会导致可执行文件增大(冗余),也就是牺牲空间来换取时间五、为什么内联函数会提高程序运行速...

2019-10-04 15:00:09 389

原创 虚函数详解

一、什么是虚函数类的成员函数前加 virtual 这种函数就叫做虚函数二、和虚函数相关的一些概念1、纯虚函数:在虚函数的声明的后面添加=0,这种虚函数就叫纯虚函数。可以不实现,但如果实现必须在类外(只能在父类的构造函数、析构函数中调用)2、抽象类:成员函数中有纯虚函数,这种类叫抽象类,抽象类不能实例化(不能创建对象),抽象类必须被继承且纯虚函数被覆盖后,由子类实例化对象,如果继承抽象类,但...

2019-10-04 11:07:58 8086

原创 链表和数组优缺点

一、数组的优点随机访问性强,查找速度快二、数组的缺点1、对内存的要求高,必须要连续的内存空间2、插入和删除的效率比较低3、数组大小固定,动态拓展性差,而且可能浪费内存三、链表的优点1、对内存的要求低2、大小可以不固定,内存的利用率比较高3、插入和删除方便四、链表的缺点查找效率低,不可以随机查找,每次查找必须从头开始...

2019-10-03 20:28:32 5820

原创 C/C++的区别

1、C语言是面向过程的语言,C++是面向对象的语言2、C语言用的是GCC编译器(现在也可以编译C++了),C++用的是G++编译器3、布尔类型是C++的关键字,但是不是C语言的关键字4、标准输入流输出流不同(C语言中是用scanf/printf实现的C++中是靠cin/cout(cout是 ostream 类型的对象,cin 是 istream 类型的对象)类实现的)5、在C++中可以函数...

2019-10-03 20:16:56 448

原创 死锁产生的条件和预防方法

一、什么是死锁多个线程都在等待对方的资源,在没有得到资源之前,都不会释放自己的资源,这样造成的循环等待现象,称为死锁。二、死锁产生的四大条件1、资源互斥2、占有,还想占有(请求并保持)3、资源不可剥夺4、环路等待(互相等待)三、预防方法构成死锁的四个条件只要破坏其中一个就构不成死锁,死锁一旦形成就无法消除,因此最好的方法就是避免产生死锁。1、破坏互斥条件,让资源能够共享,但缺点是...

2019-09-28 21:00:42 554

原创 static关键字的作用

一、static修饰局部变量1、不加static修饰,局部变量在函数或者代码块中执行完毕后就直接回收销毁了,每次执行都会重新分配内存。2、加了 static 修饰,局部变量在函数或者代码块中执行第一次初始化分配内存后,就算在函数或者代码块中执行完毕,该变量也不会被回收、销毁,一直会到程序结束 static 变量才会被回收。注意:加了static关键字后局部变量的位置会从栈空间转到全局数据区(...

2019-09-24 14:32:14 377

原创 volatile关键字

一、编译器的优化1、什么是编译器的优化?在本次线程内, 当读取一个变量时,为提高存取速度,编译器优化时有时会先把变量读取到一个寄存器中;以后,再取变量值时,就直接从寄存器中取值;当变量值在本线程里改变时,会同时把变量的新值copy到该寄存器中,以便保持一致。2、编译器优化带来的问题当变量在因别的线程等而改变了值,该寄存器的值不会相应改变,从而造成应用程序读取的值和实际的变量值不一致。当该...

2019-09-23 20:59:50 202

原创 单例模式

一、什么是单例模式只能创建出一个类对象(只有一个实际的实例)的叫做单例模式。注意:1、单例类只能有一个实例。2、单例类必须自己创建自己的唯一实例。3、单例类必须给所有其他对象提供这一实例。从具体实现角度来讲就是三点:1、单例模式的类只提供私有的构造函数。2、类定义中含有一个该类的静态私有对象。3、该类提供了一个静态的公有的函数用于创建或获取它本身的静态私有对象。二、为什么使用单...

2019-09-22 15:42:42 148

原创 二分查找

一、二分查找(时间复杂度 O(log2n))1、什么是二分查找首先假设数据是升序的,然后记录下中间的数据,让要查找的数据与它比较,如果相等那么查找成功,如果不相等,那么把数据以这个中间的数据为界限分成前后两部分,如果要查找的数据比中间的这个数据小那么就去前半部分查找,如果要查找的数据比中间的这个数据大那么就去后半部分查找,重复以上过程,直到找到满足条件的数据,如果出现左边的数据比右边的大,那么...

2019-09-22 11:24:10 139

原创 大华面试题:用函数找出一个整型数组中第二大的数

一、函数代码基本思想:用选择排序第一遍排序,先找出最大值,然后之前的数就是第二大的数,但是有两个个特殊情况要注意:1、数组刚好是有序的2、后面出现的数字比max小,但是比_max大int func(int* arr,int len){ //max是最大的数,_max是第二大的数 int max = arr[0],_max = 0; bool flag = true; //...

2019-09-20 12:00:26 699 2

原创 C++面向对象的三个基本特征

一、三大特征封装,继承,多态。二、封装所谓封装就是把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏.封装是面向对象的特征之一,是对象和类概念的主要特性. 简单的说,一个类就是一个封装了数据以及操作这些数据的代码的逻辑实体。在一个对象内部,某些代码或某些数据可以是私有的,不能被外界访问。通过这种方式,对象对内部数据提供了不同级别的保护,以防...

2019-09-19 20:03:53 4418

原创 OSI参考模型与TCP/IP参考模型

1、OSI从下到上一共七层:物理层、数据链路层、网络层、传输层、会话层、表示层、应用层。2、TCP/IP目前只实现了四层,从下到上:物理层:负责通信网络收发数据包。网络层:选择、流量控制、网络拥塞,IP协议是该层的核心。传输层:机器之间建立用于会话的端到端连接(用于数据传输),该层的核心是TCP/UDP。应用层:主要为用户提供针对性的服务,这一层的代表协议有:HTTP,SMTP,FTP,...

2019-09-19 16:50:57 450

原创 选择排序

一、选择排序(不稳定 时间复杂度:O(N²))选择排序的工作原理是每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到全部待排序的数据元素排完。二、代码//交换两个数的值#define swap(a,b) {typeof(a) t=a; a=b; b=t;}// 选择排序...

2019-09-19 15:50:56 118

原创 指针函数与函数指针的用法与区别

一、区别1、指针函数:指的就是返回值是指针的函数,本质就是个函数。2、函数指针:指的是指向函数的指针变量,本质就是个指针。二、用法1、指针函数:int* func(int a,int b);普通函数就是int func(int a,int b);,返回值是int,而指针函数就是返回值是指针的函数,即返回值是int*。2、函数指针:int (*func)(int x,int y);这里......

2019-09-16 20:16:58 15773 2

原创 const与指针的配合使用

1、const char* p(char const *p)保护的是指针指向的数据,不能通过该指针修改数据。错误例子:#include <stdio.h>int main(){ char str[] = "hehe"; const char* p = str; //str[0] = 'a'; p[0] = 'a'; return 0;}运行结果:test...

2019-09-16 19:26:19 371 2

原创 Linux常见的基础指令

一、不懂的命令man 命令(查用法、全称),只记得关键词,可用man -k 关键词。二、系统信息1、who am i :查看当前使用的终端2、who 或 w : 查看所有终端3、date :显示系统日期4、clear :清空命令行5、ifconfig :显示或设置网卡(查ip等)6、kill -9 进程号 :强制杀死进程三、文件和目录操作1、cd :进入该用户的主目录 ~(ro...

2019-09-15 16:05:26 167

原创 线程同步的方式

一、线程的同步线程同步:即当有一个线程在对内存进行操作时,其他线程都不可以对这个内存地址进行操作,直到该线程完成操作, 其他线程才能对该内存地址进行操作,而其他线程又处于等待状态。简单点来说就是线程同步事情只能一件一件做,这件事做完了才能做下一件事。注意:“同”字从字面上容易理解为一起动作,但其实不是的,“同”字应是指协同、协助、互相配合。举个例子:进程或线程A和B一块配合,A执行到一定程度时...

2019-09-11 19:35:26 249

原创 进程和线程的区别

一、进程进程是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。简单点来说就是运行中的程序。二、线程线程是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。简单点来说线程就是进程中的执行线路。三、进程和线程的区...

2019-09-02 20:16:23 142

原创 TCP和UDP的优缺点以及区别

一、TCP(传输控制协议)TCP是一种面向连接的、可靠的、基于字节流的传输层通信协议,速度相对较慢,一般应用在对安全性、完整性有严格要求的场景,如FTP、SMTP、HTTP等。三次握手:TCP为了保证报文传输的可靠,就给每个包一个序号,同时序号也保证了传送到接收端实体的包的按序接收。然后接收端实体对已成功收到的字节发回一个相应的确认,如果发送端实体在合理的往返时延内未收到确认,那么对应的数据(...

2019-09-02 19:57:10 10294

原创 指针和引用的相同点和不同点

一、指针下面这个超链接是之前写的关于指针的详解指针详解二、引用引用就是某一变量(目标)的一个别名,对引用的操作与对变量直接操作完全一样。简单点说就是声明一个标识符为引用,就表示该标识符是另一个对象的外号。三、引用和指针的相同点1、指针和引用都可以优化传参效率四、引用和指针的不相同点1、指针占内存空间,引用不占内存空间2、指针可以为空,但是引用不能为空3、指针可以不初始化,但是引...

2019-09-02 16:51:51 5948 2

原创 重载、覆盖和隐藏的区别

一、重载重载简单的来说就是在同一作用域下,函数名字相同但是函数的参数列表不同(包括参数个数和参数类型)就构成了重载,但是与返回值无关。二、覆盖1、首先覆盖必须是虚函数(被virtual修饰的函数)2、必须是子类的虚函数覆盖父类的虚函数3、函数签名必须相同(参数列表必须完全一致,const属性也会影响覆盖的结果)4、返回值必须是同类或者父子类(子类的返回值要能向父类进行隐式转换)三、隐...

2019-08-29 20:40:23 808

原创 插入排序

插入排序(Insertion sort)是一种简单直观且稳定的排序算法。如果有一个已经有序的数据序列,要求在这个已经排好的数据序列中插入一个数,但要求插入后此数据序列仍然有序,这个时候就要用到一种新的排序方法——插入排序法,插入排序的基本操作就是将一个数据插入到已经排好序的有序数据中,从而得到一个新的、个数加一的有序数据,算法适用于少量数据的排序,时间复杂度为O(n^2)。是稳定的排序方法。插入算...

2019-08-24 14:47:33 895

原创 new/delete和malloc/free的异同点

一、new/delete1、new(新建)用于新建一个对象。new 运算符总是返回一个指针(由 new 创建)。2、delete(删除)释放程序动态申请的内存空间。delete 后面通常是一个指针或者数组 [],并且只能 delete 通过 new 关键字申请的指针,否则会发生段错误。二、malloc/free1、mallocmalloc 的全称是 memory allocation...

2019-08-16 20:14:50 1313

原创 结构体对齐和补齐(详细解释)

struct sum{ char a[18]; double b; char c; int d; short e;}

2019-08-16 17:28:25 9162 13

原创 冒泡排序

一、冒泡排序算法的原理如下:1、比较相邻的元素。如果第一个比第二个大,就交换他们两个。2、对每一对相邻元素做同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。3、针对所有的元素重复以上的步骤,除了最后一个。4、持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较二、时间复杂度冒泡排序的最好时间复杂度为O(n),冒泡排序总的平均时间复杂度为O...

2019-08-12 21:02:50 225 2

原创 指针全面详解

指针是一种数据类型,是无符号整数,不过这个整数有特殊意义,它代表着内存编号。先来看个例子#include <stdio.h>int main(){ int num = 111; int* p = &num; *p = 222; printf("*p的值是:%d, p的值是:%p\n",*p,p); printf("num的值是:%d, num的地址是:%p\...

2019-08-11 23:37:44 1173 2

原创 fork,vfork,fork和vfork区别详解

forkpid_t fork(void);功能:创建一个新进程。返回值:一次调用两次返回,子进程返回0,父进程返回子进程ID,出错返回-1。1、两次返回分别是进程ID和0,父进程会拿到子进程的ID,子进程返回0,借此可以分别出父子进程,编写不同的处理分支。2、通过fork创建的子进程就是父进程的副本(拷贝),子进程会获取父进程数据段、bss段、堆、栈、IO流(共享文件指针和文件描述符)...

2019-08-07 17:29:19 421 2

原创 UNIX,Linux,信号详解

一、什么是信号信号是一种中断,即中止(注意不是终止)当前正在执行的任务,转而执行其它任务(可能返回也可能不返回),中断分为硬件中断(硬件设备产生的中断)和软件中断(其它程序产生的中断)。软中断信号(signal,又简称为信号)用来通知进程发生了异步事件。进程之间可以互相通过系统调用kill发送软中断信号。内核也可以因为内部事件而给进程发送信号,通知进程发生了某个事件。注意,信号只是用来通知某...

2019-08-05 19:06:00 156 2

原创 递归

什么是递归,说白了就是程序自己调用自己。那么在什么情况下要使用递归呢1、问题过于复杂无法拆解成循环语句。2、问题非线性,而函数递归,由于借助栈内存(函数的每一次调用,就会把它的数据重新压入到栈空间,它的数据都会保留下来),可以解决非线的问题(如汉诺塔问题)。这里要注意:在单线程模式下只能同时执行一个函数,当函数自己调用自己时(子级),会先执行子级的代码,然后子级执行完成后再返回到上一级继续执...

2019-08-04 18:57:43 286 2

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除