这篇笔记是对教程:write a hash table 的学习总结。该教程使用C语言,从零开始实现了一个哈希表,教程中哈希表实现使用了开放地址法,双重哈希等技术。本篇笔记中部分内容对原教程进行了拓展。
什么是哈希表?
哈希表(Hash Table)是一种基于键值对(Key-Value)存储的高效数据结构,通过哈希函数(Hash Function)将键(Key)映射到数组的特定位置(桶),从而实现平均 O(1) 时间复杂度的插入、查找和删除操作。
下面是基于哈希表存储电话簿的结构图:
这篇笔记是对教程:write a hash table 的学习总结。该教程使用C语言,从零开始实现了一个哈希表,教程中哈希表实现使用了开放地址法,双重哈希等技术。本篇笔记中部分内容对原教程进行了拓展。
哈希表(Hash Table)是一种基于键值对(Key-Value)存储的高效数据结构,通过哈希函数(Hash Function)将键(Key)映射到数组的特定位置(桶),从而实现平均 O(1) 时间复杂度的插入、查找和删除操作。
下面是基于哈希表存储电话簿的结构图:
音频编码是指将声音信号(通常是模拟信号)转换为数字数据的一种技术和过程。音频编码通过一定的算法或格式,对声音信号进行数字化处理和压缩,生成适合存储、传输或播放的音频文件。编码的核心是减少音频文件的体积,同时尽可能保留原始声音的质量。
音频编码分为采样与量化以及数据压缩两大部分。采样与量化是将将连续的模拟声音信号转换为离散的数字信号(即数字化)。采样与量化具体过程包括:
数据压缩是对数字化后的音频数据进行编码以减少文件大小。数据压缩分为:
CMake是一个跨平台的自动化构建系统,它使用配置文件(CMakeLists.txt)来生成标准的构建文件,如Unix的Makefile或Windows的Visual Studio工程文件。CMake旨在支持多平台源代码编辑和管理,并且可以用于管理复杂项目和大型代码库的构建过程。
CMake的主要特点包括:
跨平台: 支持在多种操作系统上构建项目,包括Windows、Linux、macOS等。
生成构建系统: 根据CMakeLists.txt文件生成适用于不同平台的构建系统或IDE项目文件。
可扩展: 允许用户通过编写自己的CMake模块和脚本来扩展其功能。
查找依赖: 能够自动查找并配置项目所需的外部库和依赖项。
配置选项: 提供丰富的配置选项,允许用户自定义构建类型、编译选项等。
安装规则: 支持定义安装规则,方便软件的打包和分发。
集成测试: 支持集成测试,确保代码质量。
社区支持: 拥有一个活跃的社区和丰富的在线资源,包括文档、教程和论坛。
适用于大型项目: 特别适合于大型项目和多语言支持的项目。
CMake通过提供一套统一的构建和配置接口,简化了在不同平台上编译和构建项目的复杂性,是许多开源项目和商业软件所采用的构建工具之一。
在学习和使用 Go 语言的过程中,我们不可避免地会遇到一些陷阱和常见的使用错误。这些建议性错误或潜在的问题,有时可能会在代码中悄悄滋生,直到某一天给你带来难以察觉的 bug。为了帮助大家更好地理解和规避这些陷阱,我整理了一些 Go 语言中常见的使用错误,这些建议或许能成为你编写更健壮、可维护代码的助力。
本篇博客旨在提醒读者注意一些在 Go 语言中易犯的错误,不仅包括语法和语义级别的问题,还包括一些最佳实践和规范。通过深入理解这些错误,我们可以更好地规避潜在的风险,写出更高效、更稳定的 Go 代码。
在我们开始探索这些错误之前,让我们一同回顾一下“在错误中学习,不断成长”的理念。编程世界中,错误不是失败的代名词,而是成长的机会。当我们深入了解常见错误时,我们更能够逐步提升自己的编程技能,写出更加健壮的代码。
愿这篇博客能够帮助你更好地使用 Go 语言,避免一些不必要的困扰。让我们开始我们的探索之旅,一同领略 Go 语言的优雅之美,并在编程的路上越走越远。
Happy coding! 🚀
append操作是并发不安全的,在使用过程中,需要特别注意。下面代码中是有问题的:
1 | func append_to_slice(s []int, i int) { |
解决办法之一是我们可以使用sync.Mutex进行加锁处理。
原文: SSL and SSL Certificates Explained For Beginners
安全套接字层 (SSL,全称Secure Sockets Layer) 和传输层安全 (TLS,全称Transport Layer security) 是通过计算机网络或链接提供安全通信的协议。它们通常用于网页浏览和电子邮件。在本教程中,我们将了解学习到:
TLS 基于 SSL,并作为替代方案而开发以应对 SSLv3 中的已知漏洞。SSL 是常用术语,我们说的 SSL 通常指的就是 TLS。
SSL/TLS 提供数据加密、数据完整性和身份验证功能。这意味着当使用 SSL/TLS 时,你可以确保:
在两方之间发送消息时,你需要解决两个问题。
这些问题的解决办法是:
这两个过程都需要使用密钥。这些密钥只是数字(常见的是 128 位),然后使用特定方法(通常称为算法)与消息组合,例如RSA,对消息进行加密或签名。
原文:Running Rust on Microcontrollers
Rust
是一个相当新的编程语言(它诞生于20101年),但在开发嵌入式固件方面显示出巨大的潜力。它首先被设计为一种系统编程语言,这使得它特别适合用于微控制器。它试图通过实现一个强大的所有权模型(可以消除整个错误类的发生)来改进 C/C++
的一些最大缺点,这对固件也非常适用。
截至2022年,C
和 C++
编程语言仍然是嵌入式固件的事实标准。然而 Rust
在固件中的角色看起来很光明。Rust
对固件的支持并不是后面才考虑到,而是一开始就考虑支持。 为此,Rust
专门有官方的 嵌入式设备工作组 和 介绍如何使用 Rust
进行嵌入式开发的 嵌入式Rust之书。下图就是Rust嵌入式设备工作组logo2。
本篇文章旨在探索在微控制器(这里指的是低级嵌入式固件,而不是在 Linux
等主机环境上运行)上运行 Rust
,涵盖以下内容:
最近在部门中做了一次技术分享,现将分享内容总结成博文发布出来,内容有删改。
Golang以并发见长,支持成千上万个协程调度。Golang中协程称为Goroutine,它是Go runtime调度中的最小执行单元,Goroutine的创建、管理、调度运行的机制采用的GMP模型。本次分享介绍的就是Golang调度机制的GMP模型。
并行(Parallelism) 指的是一个CPU时间片内可以同时做多件事情。并行强调的是某一时间点内能够同时处理多件事情,并行需要多核CPU提供支持。并行是并发的子集。
并发(Concurrency) 指的是是一种同时处理许多事情的能力,并行强调是某一时间段内能够同时处理多件事情。
最近读了《Operating Systems: Three Easy Pieces》一书,全书主要围绕虚拟化、并发和持久化这三个主题展开,其中并发部分中介绍锁的章节,行文风趣幽默,写得非常精彩。文中介绍了多种实现锁的方案,以及各种锁的适用场景和优缺点。本文基于该书中锁章节,以一个gopher的角度去分享、拓展书中介绍的锁,并尽量使用Go实现书中介绍的几款自旋锁。
锁(lock)的目的是给临界区(Critical Section)加上一层保护,以保证临界区中代码能够像单条原子指令一样执行。临界区指的是一个访问共享资源的程序片段,比如对全局变量的访问、更新。在Linux系统中保护临界区的机制除了锁之外,还有信号量,屏障,RCU等手段。
锁本质是一个变量,我们通过lock()和unlock()这两个语义函数来操作锁变量。当线程准备进入临界区时候,会调用lock()尝试获取锁,当该锁状态是未上锁状态时候,线程会成功获取到锁,从而进入到临界区,如果此时其他线程尝试获取锁而进入临界区,会阻塞或者自旋。获取锁并进入临界区的线程称为锁的持有者,当锁持有者退出临界区时候,调用unlock()来释放锁,那么阻塞等待的其他线程继续开始竞争这个锁。下面是获取锁和释放锁的代码示例:
1 | lock_t mutex; |