自定义博客皮肤VIP专享

*博客头图:

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

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

博客底图:

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

栏目图:

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

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

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

原创 effective C++ 条款3 const成员函数

条款3中关于const成员函数避免重复的例子:class TextBlock{public:...const char& operator[] (std::size_t position) const {...... return text[position];}char& operator[] (std::size_t position) { return const_cast<char&>(static_cast<const TextBl.

2022-01-08 23:48:56 274 1

原创 编码 - 自动操作/取址执行

我们可以通过RAM和加法器构造一个累加器,如下图所示:(1) 步骤1) 首先闭合清零开关,清除锁存器中的内容并把16位计数器的输出置位0000H2) 当清零开关第一次断开时,RAM阵列的地址输入是0000H,RAM阵列的该地址中存放的8位数值是加法器的输入数据。加法器的另一个输入数据为00H,因为此时锁存器也已经清零了振荡器提供的时钟信号3) 当时钟信号由0变为1时,锁存器保存加法器的计算结果,同时16位计数器增1,指向RAM阵列的下一个地址单元(0001H)4) 当时钟发生第二次跳变时,锁存.

2021-11-21 23:52:07 636

原创 编码 - 存储器/内存对齐

写操作1) 利用之前的锁存器,将输入信号写入电路中。现在Q输出端被称为数据输出端(Data Out),时钟输入端(保持位)称为写操作端(Write)。就像信息可以被记录在纸上一样,写操作端的信号同样使得数据输入(Data In)信号被写入(Written Into),也可以称之为被存储(stored)到电路中。一般情况下,如果写操作端为0,则数据输入信号的状态对输出无影响。而当我们想把数据输入信号存储在触发器中时,可以把写入信号应先置1后置为02) 我们可以把多个1位锁存器组织成多位锁存器,所要做.

2021-11-21 10:24:34 896

原创 编码 - 反馈与触发器(内存保存一位)

振荡器(oscillator),状态改变不需要人为的干预1) 如下图所示,当开关闭合后,电路就连通了,连通的电路使得电磁铁把金属簧片拉了下来,当金属簧片的位置变化时,电路不再连通,电磁铁不再具有磁性,金属簧片又弹回原位,如此一来,电路又一次连通了。从整个过程来看,开关一旦闭合,金属簧片就会上下跳动2) 电路可以简化为如下图,反向器中的继电器会在连通与断开这两种状态之间反复交替。这里反向器的输出同时又是输入,但是输出与输入却是相反的,反向器本质上是一个继电器,而继电器将状态取反以得到另一个状态是需要一.

2021-11-18 23:40:15 1134

原创 编码 - 减法器

补码加减运算公式[A + B]补 = [A]补 + [B]补[A - B]补 = [A]补 + [-B]补[-B]补 = [﹁B]补 + 1为了既能做加法又能做减法,应该在加法器中新增求二进制补码的电路如果取反为0,异或门的输出与输入相同,如果取反为1,则输出信号反置将求补器,二进制加法器和一个异或门连接如下:1) SUB为加减转换开关。当该信号为0时,进行加法运算,为1时进行减法运算。在减法中,输入B在送入加法器之前,需要通过求补电路进行取反,同时通过设定CI为1使结果加1。而在加法.

2021-11-17 01:32:06 702

原创 编码 - 加法器

加法可以分为进位和加法和1) 进位可以看到进位和与门的输出结果是一样的2) 加法和可以看到加法和可以用异或门表示3) 两个二进制数相加的结果由异或门的输出给出,进位由与门的输出给出,因此我们可以将与门和异或门连在一起来计算两个二进制数的和一位二进制的加法可以用上述半加器表示,但是多数二进制数是多于1位的,所以需要将之前的进位纳入下一次运算。为了对三个二进制数进行加法运算,我们需要将两个半加器和一个或门做如下连接;因为两个半加法器的进位输出不会同时为1(假设第一个半加器的进位是.

2021-11-16 22:52:30 752

原创 编码 - 逻辑与开关

继电器:输入的比较弱的电流被放大到较强的输出电流,当输入的电流触发了电磁铁,电磁铁把一个弹性金属条吸附下来,就像闭合了开关一样,使电流可以从接口输出。
在布尔代数中,“+”(“∪”)表示两个集合的并集,“x”(“∩”)表示两个集合的交集1) 交换律,结合律,分配律在布尔代数中同样成立,而且在布尔代数中,加法还可以来分配乘法,这在传统的代数中是不成立的W + (B x F) = (W + B) x (W + F)2) F x F = F , F + F = F逻辑门1) 连接继电器是建立逻辑.

2021-11-16 21:13:23 859

原创 深入理解计算机系统 - 数据表示与存储

定/浮点表示 - 解决小数问题原码、补码、移码 - 解决正负问题补码是种模运算1) 时钟是一种模12系统,假定钟表时针指向10点,要将它拨向6点, 则有两种拨法:① 倒拨4格:10- 4 = 6② 顺拨8格:10+8 = 18 ≡ 6 (mod 12)模12系统中: 10- 4 ≡ 10+8 (mod 12)4 ≡ 8 (mod 12)则,称8是- 4对模12的补码 (即:- 4的模12补码等于8)2) 一个负数的补码等于模减该负数的绝对值3) 对于某一确定的模,某数减去小于模的另.

2021-11-14 23:34:59 1237

原创 深入理解计算机系统 - gdb调试

典型程序的转换处理过程:原文件(.c,文本文件) ----> 预处理 ----> .i(文本文件) ----> 编译 ----> .s(文本文件) ----> 汇编 ----> .o(二进制可重定位文件) ----> 链接 ----> (二进制可执行文件)(1) 预处理:gcc –E hello.c –o hello.i(2) 编译:gcc –S hello.i –o hello.s(3) 汇编:gcc –c hello.s –o hello.o.

2021-11-12 13:30:18 1268

原创 go 内联源码分析

caninl: src/cmd/compile/internal/gc/inl.go// Caninl determines whether fn is inlineable.// If so, caninl saves fn->nbody in fn->inl and substitutes it with a copy.// fn and ->nbody will already have been typechecked.func caninl(fn *Node) { if.

2021-08-17 08:36:19 339

原创 go 修改编译源码

Windows操作系统上编译go源码下载go的源码,在bin目录下会看到go.exe,该文件即go用来编译链接运行我们go项目,我们修改go源码后要重新生成该go.exe,这样我们的go项目会用新的源码来编译运行在go源码src目录下利用cmd运行make.bat即可重新编译生成go.exe直接运行make.bat可能会报错,因为go需要先在go1.4版本上编译,所以需要先下载go1.4版本,并生成go1.4版本的go.exe,同样是在src目录下运行make.bat如果没有安装gcc编译.

2021-08-16 21:45:40 1144

原创 从实模式到保护模式-第11章

和一大段有关的信息需要8个字节来描述,所以称为段描述符,每个段都需要一个描述符。为了存放这些描述符,需要在内存中开辟出一段空间。在这段空间里,所有的描述符都是挨在一起,集中存放的,这就构成一个描述符表最主要的描述符表是全局描述符表(GDT),所谓全局,意味着该表是为整个软硬件系统服务的。在进入保护模式之前,必须要定义全局描述符表为了跟踪全局描述符表,处理器内部有一个48位的寄存器,称为全局描述符表寄存器(GDTR)。该寄存器分为两部分,分别是32位的线性地址和16位的边界。32位的处理器具有32根地址.

2021-04-13 00:04:42 124

原创 从实模式到保护模式-第10章

和往常一样,即使在32位模式下,EIP寄存器也只有处理器内部使用,程序中是无法直接访问的,对IP和EIP的修改通常是某些指令隐式执行的,这些指令包括JMP,CALL,RET,IRET等在16位处理器中,标志寄存器FALGS是16位的,在32位处理器中,扩展到了32位,低16位和原先保持一致在16位模式下,一个程序可以自由地访问不属于它的内存位置,甚至可以对那些地方的内容进行修改。这当然是不安全的,也不合法,但却没有任何机制来限制这种行为。在32位模式下,处理器要求在加载程序时,先定义该程序所拥有的段,.

2021-04-11 15:18:02 89

原创 从实模式到保护模式-第2,3,4章

内存按照字节来组织,单次访问的最小单位是1字节,这是最基本的存储单元64位处理器包含64位的寄存器和算术逻辑部件,尽管内存的最小组成单位是字节,但是,经过精心的设计和安排,它能够按字节,字,双字和四字进行访问当采用分段策略之后,一个内存单元的地址实际上就可以用“段:偏移”或者“段地址:偏移地址”来表示,这就是通常所说的逻辑地址为了在硬件一级提供对“段地址:偏移地址”内存访问模式的支持,处理器至少要提供两个段寄存器,分别是代码段寄存器(code Segment,cs)和数据段寄存器(ds);对cs内容.

2021-03-27 23:53:54 65

原创 深入理解计算机系统 —— 第二章

由于表示的精度有限,浮点运算是不可结合的(即不能使用结合律)对于一个字长为w位的机器而言,虚拟地址的范围为0 ~ 2^w - 1,程序最多访问2^w个字节我们将程序称为“32位程序”或“64位程序”时,区别在于该程序是如何编译的,而不是其运行的机器类型某些机器选择在内存中按照从最低有效字节到最高有效字节的顺序存储对象,即最低有效字节在最前面,称为小端法;另一些机器则按照从最高有效字节到最低有效字节的顺序存储,即最高有效字节在最前面,称为大端法假设变量x的类型为int,位于地址0x100处,它的十六.

2020-06-07 22:45:59 238

原创 深入理解计算机系统 —— 第一章

源程序实际上就是一个由0和1组成的位(又称为比特)序列,8个位被组织成一组,称为字节系统中所有的信息 —— 包括磁盘文件、内存中的程序,内存中存放的用户数据以及网络上传送的数据,都是由一串比特表示的。区分不同数据对象的唯一方法是我们读到这些数据对象时的上下文。比如,在不同的上下文中,一个同样的字节序列可能表示一个整数、浮点数、字符串或者机器指令hello程序的生命周期是从一个高级C语言程序开始的,因为这种形式能够被人读懂。然而,为了在系统上运行hello.c程序,每条C语句都必须被其他程序转化为一系列.

2020-05-31 21:38:18 227

原创 有意义的命名 —— Clean Code

名副其实,如果名称需要注释来补充,那就不算是名副其实避免误导,避免用外形相似的单词,更要避免用小写字母l和大写字母O做有意义的分区,不能光是添加数据或是废话。比如a1, a2, … , aN;或者废话,比如Info和Data就像a, an 和 the一样,是意义含混的废话使用读的出来的名称使用可搜索的名称,名称长短与其作用域大小相对应,单字母名称仅用于短方法中的本地变量...

2020-05-24 13:03:02 183

原创 go 并发 —— 摘自go语言学习笔记

只须在函数调用前添加go关键字即可创建并发任务关键字go并非执行并发操作,而是创建一个并发任务单元。新建任务被放置在系统队列中,等待调度器安排合适系统线程去获取执行权。当前流程不会阻塞,不会等待该任务启动,且运行时也不保证并发任务的执行次序运行时可能会创建很多线程,但任何时候仅有有限的几个线程参与并发任务执行。该数量默认与处理器核数相等,可用runtime.GOMAXPROCS函数(或环境变量)修改。如参数小于1,GOMAXPROCS仅返回当前设置值,不做任何调整尽管可用make创建单向通道,但那没.

2020-05-18 23:07:55 162

原创 go 接口 —— 摘自go语言学习笔记

编译器根据方法集来判断是否实现了接口嵌入其他接口类型,相当于将其声明的方法集导入。这就要求不能有同名方法,因为不支持重载。还有,不能嵌入自身或循环嵌入,那会导致递归错误将对象赋值给接口变量时,会复制该对象。我们甚至无法修改接口存储的复制品,因为它也是unaddressable的,即便将其复制出来,用本地变量修改后,依然无法对iface.data赋值。解决方法就是将对象指针赋值给接口,那么接口内存储的就是指针的复制品func main() { d := data{100} var t inter.

2020-05-17 22:58:01 107

原创 go 方法 —— 摘自go语言学习笔记

如何选择方法的receiver类型:要修改实例状态,用 *T;无须修改状态的小对象或固定值,建议用T;大对象建议用 *T,以减少复制成本;引用类型、字符串、函数等指针包装对象,直接用T;若包含Mutex等同步字段,用 *T,避免因复制造成锁操作无效;其他无法确定的情况,都用 *T方法集:类型T方法集包含所有receiver T方法;类型*T方法集包含所有receiver T + *T 方法;匿名嵌入S,T方法集包含所有receiver S方法;匿名嵌入 *S,T方法集包含所有receiver S + *.

2020-05-17 22:18:31 147 1

原创 go 函数 —— 摘自go语言学习笔记

函数是代码复用和测试的基本单元函数属于第一类对象,具备相同签名(参数及返回值列表)的视作同一类型;第一类对象指可在运行期创建,可用作函数参数或返回值,可存入变量的实体。最常见的用法就是匿名函数函数只能判断其是否为nil,不支持其他比较操作从函数返回局部变量指针是安全的,编译器会通过逃逸分析来决定是否在堆上分配内存定义函数类型type FormatFunc func(string, ...interface{}) (string, error)// 如不使用命名类型,这个参数签名会长到没法看fu.

2020-05-17 21:21:52 156

原创 go 表达式 —— 摘自go语言学习笔记

位移右操作数必须是无符号整数,或可以转换的无显式类型常量func main() { b := 23 //b是有符号int类型变量 x := 1 << b //无效操作,1 << b (shift count type int,must be unsigned integer)}如果是非常量位移表达式,那么会优先将无显式类型的常量左操作数转型func main() { a := 1.0 << 3 //常量表达式(包括常量展开.

2020-05-16 15:35:42 315

原创 go 类型 —— 摘自go语言学习笔记

从计算机实现角度来看,变量是一段或多段用来存储数据的内存go变量总是有固定的数据类型,类型决定了变量内存的长度和存储格式;通过类型转换或指针操作,我们可用不同方式修改变量值,但这并不意味着改变了变量类型;因为内存分配发生在运行期,所以在编码阶段我们用一个易于阅读的名字来表示这段内存。实际上,编译后的机器码从不使用变量名,而是直接通过内存地址来访问目标数据。保存在符号表中的变量名等信息可被删除,或用于输出更详细的错误信息建议以组方式整理多行变量定义var { x, y int a, s := 100.

2020-05-16 12:00:33 120

原创 go 数据 —— 摘自go语言学习笔记

一. 字符串使用``定义不做转义处理的原始字符串,支持跨行,编译器不会解析原始字符串内的注释语句,且前置缩进空格也属字符串内容s:= `line\r\n,line 2`允许以索引号访问字节数组,但不能获取元素地址s:"abc"println(s[1])println(&s[1]) //错误,不能取地址for遍历字符串时,分byte和rune两种方式s := "宿鹏飞"for i:=0;i<len(s);i++{ //byte,不支持汉字 fmt.Println("%

2020-05-13 19:20:14 155

原创 操作系统1

OS Kernel的特征1.1 并发1.2 共享:“同时访问”,互斥共享1.3 虚拟:利用多道程序设计技术,让每个用户都觉得有一个计算机专门为他服务1.4 异步:程序的执行不是一贯到底,而是走走停停,向前推荐的速度不可预知,但只要运行环境相同,OS需要保证程序的每次运行结果也相同系统调用(来源于应用程序)(同步或异步)应用程序主动向操作系统发出服务请求异常(来源于不良的应用程序)(...

2019-10-09 10:01:14 193

原创 算法

T(n)=aT(n/b)+O(n^d)以b为底的log a>d,O(N^(以b为底的log a))以b为底的log a=d,O(N^(d*logN))以b为底的log a<d,O(N^(d))数组中每个数左边比它小的数累加和的和——改归并排序,在分完合的过程中产生和稳定排序:冒泡排序、插入排序、归并排序、桶排序(数据放到容器里,然后倒出)不稳定排序:选择排序、快速排序堆...

2019-09-20 18:33:06 106

原创 深度探索C++对象模型笔记 —— 第六章

C++程序中所有的global objects都被放置在程序的data segment,如果显示指定给它一个值,此object将以该值为初值,否则object所配置到的内存内容为0

2019-09-18 23:21:54 136

原创 深度探索C++对象模型笔记 —— 第七章

Point< float >* ptr=0;程序中什么都没发生,因为一个指向class object的指针,本身并不是一个class object,编译器不需要知道与该class有关的任何members的数据或object布局数据,所以将一个“Point的一个float实例”实例化也就没有必要了如果是引用呢,假设const Point< float >&ref...

2019-09-18 23:21:44 161

原创 Effective C++笔记 —— 第八章

当operator new抛出异常以反映一个未满足的内存需求之前,它会先调用一个客户指定的错误处理函数,一个所谓的set-new-handlernamespace std{ typedef void(*new_handler)(); new_handler set_new_handler(new_handler p) throw();}new_handler是个typedef,定义出一...

2019-09-17 15:46:34 107

原创 Effective C++笔记 —— 第七章

以不同template参数具现化function templates会导致调用不同的函数,这便是所谓的编译器多态;哪一个重载函数被调用也是发生在编译期如果template内出现的名称如果相依于某个template参数,称之为从属名称。如果从属名称在class内呈嵌套状,我们称它为嵌套从属名称,如果解析器在template中遭遇一个嵌套从属名称,它便假设这个名称不是个类型,除非你告诉它是。比如 ...

2019-09-16 22:53:28 126

原创 Effective C++笔记 —— 第六章

public继承是is-a的关系derived class作用域相当于base class作用域不重新定义继承而来的缺省参数值,virtual函数动态绑定,而缺省参数值却是静态绑定

2019-09-16 20:13:04 129

原创 Effective C++笔记 —— 第五章

转型1.1 const_cast 通常被用来将对象的常量性转除,它也是唯一具有此能力的C++转型操作符1.2 dynamic_cast 主要用来执行“安全向下转型”(父类转为子类),也就是用来决定某对象是否归属继承体系中的某个类型。它是唯一无法由旧式语法执行的动作,也是唯一可能耗费重大运行成本的转型动作1.3 reinterpret_cast 意图执行低级转型,实际动作及结果可能取决于编译...

2019-09-11 19:15:12 104

原创 深度探索C++对象模型笔记 —— 第五章

inline和define

2019-09-10 21:09:10 218

原创 深度探索C++对象模型笔记 —— 第四章

静态成员函数不能直接存取其class中的nonstatic members;不能够被声明Wieconst,volatile或virtual;它不需要经由class object才被调用——虽然大部分时候它是这样被调用的ptr->z();一般而言,每次调用z()时,并不知道ptr所指对象的真正类型,然而我们知道经由ptr可以存取到该对象的virtual table;虽然不知道哪一个z(...

2019-09-03 21:14:38 222

原创 深度探索C++对象模型笔记 —— 第二章

有四种情况,编译器必须为未声明构造函数的类合成一个默认构造函数,四种情况为:“带有默认构造函数”的成员类对象,“带有默认构造函数”的基类,“带有虚函数”的类,在继承链中有虚继承的。至于没有存在这四种情况而又没有声明任何构造函数的class,它们拥有的是implicit trivial default constructions,它们实际上并不会被合成出来在合成的默认构造函数中,只有base c...

2019-09-03 20:00:56 149

原创 深度探索C++对象模型笔记 —— 第三章

空类的大小是1,为了使得这一class的两个object得以在内存中配置独一无二的地址

2019-09-03 20:00:27 157

原创 深度探索C++对象模型笔记 —— 第一章

C++在布局以及存取时间上主要的额外负担是由virtual引起的,包括虚函数和虚继承多态是通过指针或引用来完成的Librarary_meterials thing1; class Book:public Librarary_meterials {...}; Book book; //thing1不是一个Book,book被裁切了,不过thing1仍保有一个Librarary_meteri...

2019-09-02 11:41:26 239

原创 面向对象高级编程

相同class的各对象互为友元class complex{ public: complex(double r=0,double i=0) : re(r),im(i) {} int func(const complex& param) { return param.re+param.im; } private: double ...

2019-08-28 15:03:10 152

原创 多线程编程1

管理线程的函数和类在< thread >中声明,而保护共享数据的函数和类在其他头文件中声明每个线程都必须有一个初始函数,新线程的执行从这里开始。对于应用程序来说,初始线程是main(),但是对于其他线程,可以在std::thread对象的构造函数中指定,本例中,被命名为t的std::thread对象拥有新函数hello()作为其初始函数与直接写入标准输出或是从main()调用he...

2019-08-26 00:21:32 72

原创 STL源码剖析笔记 —— 第六章

将无效的迭代器传给某个算法,虽然是一种错误,却不能保证能够在编译时期就被捕获出来,因为所谓“迭代器类型”并不是真实的型别,它们只是function template的一种性别参数对于所有的数值(numeric)算法,包括adjacent_difference(),accumulate(),inner_product(),partial_sum()等等,均需要包含头文件< numeric ...

2019-08-26 00:20:23 124

空空如也

空空如也

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

TA关注的人

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