谷歌发现的十条真理

Google的网站上有一个网页,叫做“我们的哲学”(Our Philosophy),上面列出了十句话。 1. 用户第一,然后其他事情就会发生。 (Focus on the user and all else will follow.) 2. 最好的方法就是把一件事情做到非常、非常好。 (It’s best to do one thing really, really well.) 不要在乎自己现在的状况,如果你不断地正确地做一件事情,总有一天会有不一样的结果。 3. 快比慢好。 (Fast is better than slow.) “我们也许是世界上唯一一家希望用户尽快离开自己网站的公司:最快地给出用户想要的结果,一个多余的字节也没有,并且还在致力于变得更快。” 4. 民主在网上很管用。 (Democracy on the web works.) 相信民主的人在互联网上能获得成功,相信管制和独裁的人在互联网上必将遭到失败。 5. 要寻找答案,不一定需要办公桌。 (You don’t need to be at your desk to need an answer.) 6. 不干坏事,也能挣到钱。 (You can make money without doing evil.) 当考验来临时,要将信念置于金钱之上。坚信人生中有比金钱和物质更重要的东西,更加坚信这样做的人最终会赢得信赖和回报。 7. 未知的信息总是存在的。 (There’s always more information out there.) ...

August 6, 2022 · 1 min · Rancho

计算机基础补全计划

自己虽然是写程序的,但是专业是自动化,毕竟不是计算机科班出身,还是要补一补计算机基础的; 计算机基础: 计算机组成原理; 《深入理解计算机原理》 操作系统; 《操作系统导论》 计算机网络; 《计算机网络:自顶向下方法》 数据结构与算法; 编译原理; 学习过程记录: 先学习计算机网络,正好视频跟课本是配套的: 参考B站视频,争取一个月内补全计算机网络相关的知识; 链接:https://www.bilibili.com/video/BV1JV411t7ow?spm_id_from=333.337.search-card.all.click&vd_source=d3e0d33e56175cb1e5a020e1a154d370 到今天为止,把计算机网络的内容过了一遍,满打满算花了一个月吧,后续肯定还需要更多的时间去消化这些知识内容; 后续看一下计算机系统整体相关的知识吧,大四这一年应该是难得的知识摄入的时间。

July 27, 2022 · 1 min · Rancho

我会成为自己所期望的那个工程师吗

昨天收到了大疆的录用意向offer,很开心,从四月投递简历,到终面结束,再到昨天收到意向offer,自己花了很多的时间和精力去修改简历和准备面试,终于还是等到了; 关于DJI面试 收到意向offer的时候,我正在海康的三楼餐厅吃饭,看到是深圳的电话,我就猜到是大疆的HR打来的; 我很早就听说过大疆,那时候只是知道大疆是一家做无人机的公司,更多的就没有什么了解了; 大二开学,我报名参加了我们学校的RoboMaster战队,在队内总共呆了一年,主要是负责哨兵机器人的嵌入式开发;说来惭愧,我并没有为我们队伍做出过什么大的贡献,自己也没有做什么创新性的东西,充其量我的表现是中规中矩,大多数时候都是在补充自己的知识储备,不过正是通过这个比赛我才更近距离地接触到大疆,也认识了挺多学长学姐,这对我的影响很大; 在备赛过程中,我用过大疆的无刷电机,很强,功能很强,控制尤其方便,还勾起了我对无刷电机控制的兴趣,学了一点FOC,然后用开源的Simple FOC,做了一个简单的无刷电机驱动器,很有意思,在大疆的面试中,面试官问我:“你能不能说一个你用过的大疆的产品的一个缺点?”,我就提到了这件事,并说了一个我认为大疆的无刷电机所存在的缺点。 我只去过一次比赛现场,感受过那种赛场的氛围,很难忘的经历,在面试中,面试官问了我一个问题: “你对大疆印象最深的是什么?” “我印象最深的就是是大疆的社会责任感,因为我去过比赛现场,所以我很感激大疆提供的这种难得的机会,对我这样的人来说,这是很难忘也很难得的机会;” 不知道面试官对我的回答是否满意,但这的确是我心里的想法; 我想,今天这个日子,几年或者更久的时间后,再回头来看,可能会说今天是一个十分重要的日子; 4月25日,我投出了我的简历;然后按部就班,面试面试还是面试,一共三轮面试,最后就是等offer; 在准备面试中,花了很多精力,学了好多东西,实时操作系统的知识还有C语言和ARM内核相关的知识,也把自己做过的项目,参加过的比赛都捋了好多遍,生怕面试官问到这方面的内容,自己却答不上来; 这是我第一次投简历和面试,之前听说找工作时永远不要将自己最想去的公司放在第一个,因为第一次总是没有经验,总会紧张。所以如果第一次就要投最想去的公司,那就要认真准备了; 准备面试的那几个星期我记了好多笔记,梳理了知识点,理通了自己做过的所有的项目还考虑了面试官可能问到的各种问题,记了几万字的笔记; 我还记得那个下午,我在自习室坐了一天,把FreeRTOS的相关知识从头到尾梳理了一遍; 准备的越多,自己就越有底气; 虽然面试中并没有问到很多自己准备的问题,但是准备的过程还是很大程度上减弱了自己的紧张; 虽然付出并不总是有收获的; 但是想到自己经常熬夜去解决一个又一个Bug,熬夜画一个又一个板子,自己乐在其中,享受做东西的快乐; 关于我的愿望 我QQ签名是: 立志成为一名嵌入式开发攻城狮! 是的,成为一名工程师是我一直以来的愿望; 前些天我又看了一遍《三傻大闹宝莱坞》,每次看的感觉都不一样; 第一次看这部电影是在我六年级的时候,那个时候觉得做一名工程师好酷,好像什么都能做出来,好像能解决遇到的一切问题,还有着不错的薪资; 现在想来,梦想成为一名工程师的想法就是从那个时候开始的吧; 兰彻,聪明,幽默,还有很多奇葩的想法,这部电影,让我觉得,做一名工程师会是多么有意思的事情呀; 能用自己的知识解决遇到的各种问题,而且乐在其中; 路一步步走,越走就离自己最初的想法越近; 最后我想说 我想,我会成为自己想成为的那个工程师,掌握很多技能,面对问题,自己总能想到办法; 我相信我会成为这样的人:聪明、乐观、幽默、不言放弃、坚信问题终会被解决; 正式OFFER(2022年10月31号更新) 上周五中午接到电话,谈了薪水,晚上收到了正式OFFER,然后沟通了三方,尘埃落定; 说真的,大疆开的是真的高,福利也不错,我是非常满意了,所以就决定去了。 下面整理一下整个流程,也许可以帮助到后面的人: 事件 日期 投递简历 4月25日 性格测评 4月27日 第一次面试 5月3日 第二次面试 5月13日 第三次面试 5月20日 电话OC 7月22日 收到录用意向书 7月22日 谈薪电话 10月27日 收到正式OFFER 10月27日 沟通三方信息 10月28日

July 23, 2022 · 1 min · Rancho

BIN、HEX、AXF和ELF的区别

几种常见格式的区别; 一、bin文件 Bin文件是最纯粹的二进制机器代码, 或者说是”顺序格式”。按照assembly code顺序翻译成binary machine code,内部没有地址标记。Bin是直接的内存映象表示,二进制文件大小即为文件所包含的数据的实际大小。 BIN文件就是直接的二进制文件,一般用编程器烧写时从地址0x00开始,而如果下载运行,则下载到编译时的地址即可。可以直接在裸机上运行。 二、hex文件 Intel hex 文件常用来保存单片机或其他处理器的目标程序代码。它保存物理程序存储区中的目标代码映象。一般的编程器都支持这种格式。 就是机器代码的十六进制形式,并且是用一定文件格式的ASCII码来表示。 HEX文件由记录(RECORD)组成。在HEX文件里面,每一行代表一个记录。每条记录都由一个冒号“:”打头,其格式如下: 文件格式: :BBAAAATTHHHH…HHHHCC 含义分别如下: BB:字节个数; AAAA:数据记录的开始地址,高位在前,低位在后; TT: Type ; Type: 00数据记录,用来记录数据;01记录结束,放在文件末尾,用来标识文件结束;02用来标识扩展段地址的记录;04扩展地址记录(表示32位地址的前缀); HHHH:一个字(Word)的数据记录,高字节在前,低字节在后; TT之后共有 BB/2 个字的数据 。 CC: 占据一个Byte的CheckSum; 举例: 每行中的数据并不是一定有的,第二个字节数据长度为0,那么这行就没有数据。 由于每行标识数据地址的只有2Byte,所以最大只能到64K,为了可以保存高地址的数据,就有了Extended Linear Address Record。如果这行的数据类型是0x04,那么,这行的数据就是随后数据的基地址。例如: :020000040004F6 :1000000018F09FE518F09FE518F09FE518F09FE5C0 :1000100018F09FE5805F20B9F0FF1FE518F09FE51D :00000001FF 第一行,是Extended Linear Address Record,里面的数据,也就是基地址是0x0004; 第二行是Data Record,里面的地址值是0x0000。那么数据18F09FE518F09FE518F09FE518F09FE5要写入FLASH中的地址为 (0x0004 « 16) | 0x0000,也就是写入FLASH的0x40000这个地址。 同样,第三行的数据的写入地址为0x40010。当一个HEX文件的数据超过64k的时候,文件中就会出现多个Extended Linear Address Record。 校验值:每一行的最后一个值为此行数据的校验和。例如: :1000000018F09FE518F09FE518F09FE518F09FE5C0 这行中的 0xC0; :1000100018F09FE5805F20B9F0FF1FE518F09FE51D 这行中的 0x1D; 校验和的算法为:计算从0x3A 以后(不包括0x3A)的所有各字节的和模256的余。即各字节二进制算术和,不计超过256的溢出值,然后用0x100减去这个算数累加和,得出得值就是此行得校验和。 如手头的STM32 HEX 第一行 020000040800F2; End of File Record 行是每一个HEX文件的最后一行。例如: ...

July 21, 2022 · 1 min · Rancho

力扣刷题记录

记录自己刷算法题中遇到的问题和自己的思路; 1、无重复长度的最长子串: 题目描述: 提示: 0 <= s.length <= 5 * 104; s` 由英文字母、数字、符号和空格组成; 思路: 就是做两个标志位,表示当前字符串的起始位置和正在比较的字符位置; 遍历整个字符串; 从起始标志位开始,到结束位置,依次比对是否有重复字符; 如果无,就结束位置加加; 如果有,就计算长度,并移动起始位置到重复字符的下一个位置; 然后一直循环; 要特别考虑: au abb bba 这些特殊排序的字符串; 是因为最后一个没有办法比较; 题解代码: int lengthOfLongestSubstring(char *s) { int str_length = strlen(s); int end_flag = 1, start_flag = 0, max_length = 1; char flag = 0; int i = 0; if (str_length == 0) { return 0; } while (*(s + end_flag) != '\0') { for (i = start_flag; i max_length) { max_length = end_flag - start_flag; } flag = 1; break; } if (i == str_length - 2) { if ((*(s + end_flag + 1) == '\0')) { if (end_flag - start_flag + 1 > max_length) { max_length = end_flag - start_flag + 1; } } } } if (flag == 1) { flag = 0; start_flag = i + 1; } else { end_flag++; } } return max_length; 改进: //方法2 int lengthOfLongestSubstring(char * s){ int str_length=strlen(s); int end_flag=1,start_flag=0,max_length=1; char flag=0; int i=0; if(str_length==0) { return 0; } while(*(s+end_flag)!='\0') { for(i=start_flag;imax_length) { max_length=end_flag-start_flag; } flag=0; start_flag=i+1; } else { if(end_flag-start_flag+1>max_length) { max_length=end_flag-start_flag+1; } end_flag++; } } return max_length; } 2、括号匹配 ...

July 17, 2022 · 2 min · Rancho

malloc和free的用法

在C语言中,内存管理是很重要的,最近刷算法题目也用到了malloc和free函数,在此记录一下; 一、函数原型及说明: malloc(): 函数原型: void *malloc(long NumBytes); 该函数分配了NumBytes个字节,并返回了指向这块内存的指针。如果分配失败,则返回一个空指针(NULL)。 关于分配失败的原因,应该有多种,比如说空间不足就是一种。 free(): 函数原型: void free(void *FirstByte); 该函数是将之前用malloc分配的空间还给程序或者是操作系统,也就是释放了这块内存,让它重新得到自由。 二、函数使用注意事项: 1、申请了内存空间后,必须检查是否分配成功; 2、当不需要再使用申请的内存时,记得释放; 释放后应该把指向这块内存的指针指向NULL,防止程序后面不小心使用了它。 3、这两个函数应该是配对使用; 如果申请后不释放就是内存泄露;如果无故释放那就是什么也没有做。释放只能一次,如果释放两次及两次以上会出现错误(释放空指针例外,释放空指针其实也等于啥也没做,所以释放空指针释放多少次都没有问题)。 **4、虽然malloc()函数的类型是(void ),任何类型的指针都可以转换成(void ),但是最好还是在前面进行强制类型转换,因为这样可以躲过一些编译器的检查; 三、具体例子: // Code... char *Ptr = NULL; Ptr = (char *)malloc(100 * sizeof(char)); if (NULL == Ptr) { exit (1); } gets(Ptr); // code... free(Ptr); Ptr = NULL; // code... 四、原理部分: 1、malloc内存空间的来源: 答案是从堆里面获得空间。 也就是说函数返回的指针是指向堆里面的一块内存。操作系统中有一个记录空闲内存地址的链表。当操作系统收到程序的申请时,就会遍历该链表,然后就寻找第一个空间大于所申请空间的堆结点,然后就将该结点从空闲结点链表中删除,并将该结点的空间分配给程序。 在使用malloc()分配内存空间后,一定要记得释放内存空间,否则就会出现内存泄漏。 2、free释放了什么: free()释放的是指针指向的内存。 注意!释放的是内存,不是指针!指针并没有被释放,指针仍然指向原来的存储空间。指针是一个变量,只有程序结束时才被销毁。释放了内存空间后,原来指向这块空间的指针还是存在!只不过现在指针指向的内容的垃圾,是未定义的,所以说是垃圾。因此,释放内存后把指针指向NULL,防止指针在后面不小心又被解引用了。 free() 不会改变 指针变量本身的值,调用 free() 后它仍然会指向相同的内存空间,但是此时该内存已无效,不能被使用。所以建议将 指针的值设置为 NULL,例如: free(ptr); ptr = NULL; free()的源代码: struct mem_control_block { int is_available; //一般来说应该是一个可用空间的首地址,但这里英文单词却显示出空间是否可用的一个标记 int size; //这是实际空间的大小 }; void free(void *ptr) { struct mem_control_block *free; free = ptr - sizeof(struct mem_control_block); free->is_available = 1; return; } 五、直接定义一个数组和使用malloc动态分配的区别: malloc作为一个包含在头文件下的函数,用于申请空间。 ...

July 16, 2022 · 1 min · Rancho

比较好的知识网站记录

一些比较好的网站的集锦; 1、阮一峰的网络日志: Make 命令教程 主要是关于Makefile的简单教程,看了之后基本能够完成一个比较完备的Makefile; 这是我自己总结的例子:Makefile基本示例; 跟我一起写Makefile教程:跟我一起写Makefile; 网站上还有不少比较好的教程和博客:网站首页; 2、Bash脚本教程: 阮一峰的Bash脚本教程; 3、C语言入门教程: 阮一峰的C语言入门教程;

July 13, 2022 · 1 min · Rancho

GCC常见命令及用法

GCC工具介绍以及常见的用法; GCC编译命令: 1. GCC工具 GCC编译器: GCC(GNU Compiler Collection)是由 GNU 开发的编程语言编译器。 GCC最初代表“GNU C Compiler”,当时只支持C语言。 后来又扩展能够支持更多编程语言,包括 C++、Fortran 和 Java 等。 因此,GCC也被重新定义为“GNU Compiler Collection”,成为历史上最优秀的编译器, 其执行效率与一般的编译器相比平均效率要高 20%~30%。 GCC的官网地址为:https://gcc.gnu.org/,在Ubuntu系统下系统默认已经安装好GCC编译器,可以通过如下命令查看Ubuntu系统中GCC编译器的版本及安装路径: GCC编译工具链: GCC编译工具链(toolchain),是指以GCC编译器为核心的一整套工具。它主要包含以下三部分内容: gcc-core:即GCC编译器,用于完成预处理和编译过程,把C代码转换成汇编代码。 Binutils :除GCC编译器外的一系列小工具包括了链接器ld,汇编器as、目标文件格式查看器readelf等。 glibc:包含了主要的 C语言标准函数库,C语言中常常使用的打印函数printf、malloc函数就在glibc 库中。 在很多场合下会直接用GCC编译器来指代整套GCC编译工具链。 Binutils工具集: Binutils(bin utility),是GNU二进制工具集,通常跟GCC编译器一起打包安装到系统,它的官方说明网站地址为: https://www.gnu.org/software/binutils/ 。 在进行程序开发的时候通常不会直接调用这些工具,而是在使用GCC编译指令的时候由GCC编译器间接调用。下面是其中一些常用的工具: as:汇编器,把汇编语言代码转换为机器码(目标文件)。 ld:链接器,把编译生成的多个目标文件组织成最终的可执行程序文件。 readelf:可用于查看目标文件或可执行程序文件的信息。 nm : 可用于查看目标文件中出现的符号。 objcopy: 可用于目标文件格式转换,如.bin 转换成 .elf 、.elf 转换成 .bin等。 objdump:可用于查看目标文件的信息,最主要的作用是反汇编。 size:可用于查看目标文件不同部分的尺寸和总尺寸,例如代码段大小、数据段大小、使用的静态内存、总大小等。 系统默认的Binutils工具集位于/usr/bin目录下,可使用如下命令查看系统中存在的Binutils工具集: # 在Ubantu上执行如下命令 ls /usr/bin/ | grep linux-gnu- glibc库: glibc库是GNU组织为GNU系统以及Linux系统编写的C语言标准库,因为绝大部分C程序都依赖该函数库,该文件甚至会直接影响到系统的正常运行,例如常用的文件操作函数read、write、open,打印函数printf、动态内存申请函数malloc等。 在Ubuntu系统下,libc.so.6是glibc的库文件,可直接执行该库文件查看版本,在主机上执行如下命令: # 在Ubantu上执行如下命令 # 以下是Ubuntu 64位机的glibc库文件路径,可直接执行 /lib/x86_64-linux-gnu/libc.so.6 ...

July 9, 2022 · 2 min · Rancho

算数式计算

字符串算式先转为逆波兰式(后缀表达式),然后计算; 一、求逆波兰表达式 核心思想: 逆波兰算法的核心思想是将普通的中缀表达式转换为后缀表达式。 **什么是中缀表达式?**例如a+b,运算符在两个操作数的中间。这是我们从小学开始学习数学就一直使用的表达式形式。 **什么是后缀表达式?**例如a b + ,运算符在两个操作数的后面。后缀表达式虽然看起来奇怪,不利于人阅读,但利于计算机处理。 转换为后缀表达式的好处是: 去除原来表达式中的括号,因为括号只指示运算顺序,不是实际参与计算的元素。 使得运算顺序有规律可寻,计算机能编写出代码完成计算。 核心步骤: 逆波兰算法的核心步骤就2个: 将中缀表达式转换为后缀表达式,例如输入的原始表达式是 3*(5+7) ,转换得到 3 5 7 + * 根据后缀表达式,按照特定的计算规则得到最终计算结果 具体步骤: 中缀表达式转换为后缀表达式: 你需要设定一个栈SOP,和一个线性表 L 。SOP用于临时存储运算符和左括号分界符( ,L用于存储后缀表达式。 遍历原始表达式中的每一个表达式元素: 如果是操作数,则直接追加到 L中。只有 运算符 或者 分界符( 才可以存放到 栈SOP中; 如果是分界符: 如果是左括号 ( , 则 直接压入SOP,等待下一个最近的 右括号 与之配对。 如果是右括号 ) ,则说明有一对括号已经配对(在表达式输入无误的情况下)。不将它压栈,丢弃它,然后从SOP中出栈,得到元素e,将e依次追加到L里。一直循环,直到出栈元素e 是 左括号 ( ,同样丢弃他。 如果是运算符(用op1表示): 如果SOP栈顶元素(用op2表示) 不是运算符,则二者没有可比性,则直接将此运算符op1压栈。 例如栈顶是左括号 ( ,或者栈为空。 如果SOP栈顶元素(用op2表示) 是运算符 ,则比较op1和 op2的优先级。如果op1 > op2 ,则直接将此运算符op1压栈。 如果不满足op1 > op2,则将op2出栈,并追加到L,再试图将op1压栈,如果如果依然不满足 op1>新的栈顶op2,继续将新的op2弹出追加到L ,直到op1可以压入栈中为止。 ...

July 8, 2022 · 1 min · Rancho

简单Makefile

一个简单的Makefile,可以直接Copy使用; 一、用字符常量简化 Makefile文件: #定义常量 objects =main.o fun1.o #中间文件 cc=gcc #编译器 prom=main #输出文件 prom: $(objects) $(cc) $(objects) -o $(prom) main.o: main.c fun1.h $(cc) -c main.c -o main.o @echo 正在编译main文件 #前面加@避免重复输出信息 fun1.o: fun1.c fun1.h $(cc) -c fun1.c -o fun1.o @echo 正在编译其他文件 .PHONY: clean clean: -rm $(prom) $(objects) 文件夹结构: 二、更简化的写法 Makefile文件: obj=main.o fun1.o cc=gcc prom=main deps=fun1.h $(prom):$(obj) $(cc) -o $(prom) $(obj) %.o:%.c $(deps) $(cc) -c $< -o $@ 在这里,我们用到了几个特殊的宏。首先是 %.o:%.c,这是一个模式规则,表示所有的 .o 目标都依赖于与它同名的 .c 文件(当然还有 deps 中列出的头文件)。再来就是命令部分的 $< 和 $@,其中 $< 代表的是依赖关系表中的第一项(如果我们想引用的是整个关系表,那么就应该使用 $^),具体到我们这里就是 %.c。 而 $@ 代表的是当前语句的目标,即 %.o。这样一来,make 命令就会自动将所有的 .c 源文件编译成同名的 .o 文件。不用我们一项一项去指定了。整个代码自然简洁了许多。 ...

July 7, 2022 · 1 min · Rancho