摘要:
Check if your commits haveChange-Id: ...in their descriptions. Every commit should have them.you can "git log" to review your commits haveChange-IdIf no, usegit rebase -ito reword the commit messages and add proper Change-Ids (usually this is a SHA1 of the first version of the reviewed com 阅读全文
摘要:
A:区别主要是:string的内存管理是由系统处理,除非系统内存池用完,不然不会出现这种内存问题。char *的内存管理由用户自己处理,很容易出现内存不足的问题。当我们要存一个串,但是不知道其他需要多少内存时, 用string来处理就最好不过了。当你知道了存储的内存的时候,可以用char *,但是不如用string的好,用指针总会有隐患。用string还可以使用各种成员函数来处理串的每一个字符,方便处理。用char *处理串,就不如string的方便了,没有相应的函数来直接调用,而是要自己编写函数来完成串的处理,而且处理过程中用指针还很容易出现内存问题。我建议尽量使用string,不用char 阅读全文
摘要:
好久没写过c程序,都忘记了c程序中的字符串的含义。今天问过而知新,c语言字符串其实就是一个字符数组,比如char* ptr = "hello world",其实就是ptr[] = {'h','e','l','l','0',' ','w','o','r','l','d','\0'}; 声明一个字符串会自动在末尾添加一个\0 不需要人工干预。总结如下: 一个字符串必须要一个 \0 结尾 不 阅读全文
摘要:
由于利用管道实现进程间通信,是通过创建两个文件描述符,但是描述符的初始化是通过随机的,就是从可用的文件描述符中取出,并将可用的文件描述符与file对象相关联,如果我们需要将管道的两头与其他的流相关时,就需要重定向操作,重定向fd[0]和fd[1]的file,下面是关于实现重定向的函数dup和dup2的解释:系统调用dup和dup2能够复制文件描述符。dup返回新的文件文件描述符(没有用的文件描述符最小的编号)。dup2可以让用户指定返回的文件描述符的值,如果需要,则首先接近newfd的值,他通常用来重新打开或者重定向一个文件描述符。他的原型如下:#include <unsitd.h> 阅读全文
摘要:
最近在想一个问题,关于进程间通信的问题,我们都知道进程间可以通过管道通信,但是为什么进程间可以通过管道通信呢?管道通信的机制又是什么呢?我想很多人应该没有去思考过,下面我来讲讲我对管道通信机制的理解。如果两个不相关的进程打开同一个文件,一个只读方式开打,一个只写方式打开,不就相当于创建了一个管道了,进程A往里面写,进程B读,同样实现进程间通信。管道其实也一样。一般的管道,只能在父子进程间进行通信,为什么?因为管道实现的进程间通信是在父进程fork()出子进程时,子进程会继承父进程的文件描述符表,而这个文件描述符表里记录了所有父进程打开的文件,所以子进程也继承了父进程打开的文件,所以父子进程可以 阅读全文
摘要:
最近在看深入理解计算机系统,看到一个函数叫做execve(),这个函数很有意思,可以在一个进程插入另外一个进程执行,但是又不像fork()一样产生一个子进程,execve()插入的进程和原进程共享进程号,就好像执行这进程就像执行过程调用一般随意。函数原型如下:int execve(const char *filename, char *const argv[], char *const envp[]);EXAMPLE The following program is designed to be execed by the second program below. It jus... 阅读全文
摘要:
我们知道进程有自己的虚拟地址空间,并且互不干扰,那么进程间通信又如何实现呢?A又看不到B的地址,B又看不到A的地址,那A怎么访问B的东西,B又怎么访问A的东西,我想这应该得借助第三方的东西,我们都知道进程地址空间有一段内核地址,里面是进程由用户态进入内核态时进程运行的内核态环境,比如通过系统调用进入内核态获取内核服务,进程的内核态也有自己内核栈,为什么需要内核栈呢?用户栈难道不就够了吗?因为内核服务很多都是受保护的,比如访问页表,进程控制块这些东西。但是内核栈又和进程间通信有什么相关呢?对于OS所有的进程间通信都是调用系统调用实现的,所有的系统调用都要陷入到内核态去执行。问题:管道是如何实现进 阅读全文
摘要:
一个lex程序具有如下形式:声明部分:包括变量和明示常量,可以将一些c语言的东西写在%{....... %},并且可以在转换规则中调用%{ #include <stdio.h> int id_num; /*常量量*/%}letter [A-Za-z] /*正则变量*/start start /*正则变量*/stop stop /*正则变量*/转换规则:通过在声明部分的正则变量,识别输入流中的单词,并可以执行一些动作lex程序中的每个转换规则具有如下形式: 模式 {动作}%%letter {id_... 阅读全文
摘要:
最近在学习编译原理,发现以前在数据结构中学习到的KMP算法在词法分析中使用到,词法分析中要识别词法单元,构建符号表,并将识别的词法单元返回给语法分析器来处理。在这个过程中有一个状态转化的过程,如下:如要识别ababaa,状态转换图如下所示:KMP提出了一种在文本串中搜索单个关键字b1b2....bn的算法,为了快速处理文本串并在这些串中搜索一个关键字,针对关键字b1b2....bn以及该关键字中的位置s(s表示关键字b1b2....bn中的状态转换图中的状态)定义了一个失效函数f(s),f(s)的含义如下:f(s)表示匹配到状态s,但是匹配不到状态s+1,下一次从状态f(s)开始匹配。比如文本 阅读全文
摘要:
求一个数组中第k大的数,我第一印象是冒泡,因为只要冒泡k趟即可,第一趟冒泡第一大,第二次冒泡第二大,第k次冒泡第k大,时间复杂度为O(kn),n为数组长度。但是我们都知道快速排序是对冒泡的改进,降低冒泡的递归深度,使时间复杂度降低到O(nlgn),为什么不用快排呢?那么快排的时间复杂度又是多少呢?因为快排每次将数组划分为两组加一个枢纽元素,每一趟划分你只需要将k与枢纽元素的下标进行比较,如果比枢纽元素下标大就从右边的子数组中找,如果比枢纽元素下标小从左边的子数组中找,如果一样则就是枢纽元素,找到,如果需要从左边或者右边的子数组中再查找的话,只需要递归一边查找即可,无需像快排一样两边都需要递归, 阅读全文