- 博客(96)
- 收藏
- 关注
原创 【CSAPP 3.5】算术和逻辑操作
下表列出了x86-64的一些整数和逻辑操作。大多数操作都分成了指令类,这些指令类有各自带不同大小操作数的变种(除了leaq)。例如,指令ADD由4条加法指令组成:addb、addw、addl、addq,分别是字节加法、字加法、双字加法、四字加法。以下操作被分为4组:加载有效地址、一元操作、二元操作、移位。
2023-05-10 21:44:07
915
原创 【CSAPP 3.3~3.4】x86-64访问数据
一个x86-64的CPU包含一组16个存储64位值的通用目的寄存器。这些寄存器用来存储整数数据和指针,它们的名字都以%r开头。
2023-04-10 20:45:08
601
原创 【CSAPP】程序编码
用高级语言(C、Java等)编写的程序可以在很多不同的机器上编译和执行,而汇编代码则是与特定类型的机器密切相关的。即使编译器承担了生成汇编代码的大部份工作,对于严谨的程序员来说,能够阅读和理解汇编代码仍是一项很重要的技能。
2023-04-01 12:17:48
829
原创 【CSAPP】整数运算
在C语言中,整型变量占固定大小的字节和位,当整数运算结果超出了整型变量的表示范围时,计算机运算的结果是截断后的值,与预期值有偏差。
2023-02-23 21:34:01
519
原创 【CSAPP】整数表示
使用位编码整数有两种不同的方式:只能表示非负数(零、正数),即无符号数的编码。既能表示非负数,也能表示负数,即有符号数的编码、补码编码。
2023-02-19 12:11:32
517
原创 【CSAPP】计算机系统漫游
计算机系统是硬件和系统软件互相交织的集合体。我们通过跟踪hello程序的生命周期来开始对系统的学习:从它被程序员创建开始,到在系统上运行,输出简单的消息,然后终止。
2023-02-11 17:37:52
1021
2
原创 B-树和B+树
B+树是对B-树的改进,其单个非叶子节点上能保存更多的查找数据,因此在存储海量数据时,树的深度更浅;查找数据时,磁盘I/O次数更少、效率更高。
2023-02-05 22:51:55
285
原创 如何保持学习和思考
利用好时间。少花费时间在无意义的事情上。拓展思维。多了解历史、生物等其他各种领域的知识,而不仅仅局限于IT技术。保持理性。搭配好手和脑。保持包容。能容纳不同的思想和意见。...
2022-04-01 22:26:17
427
原创 【人类历史】从食物采集者到食物生产者
文章目录人类的诞生人类历史的分段旧石器时代物质生活精神生活新石器时代农业革命农牧共存社会分工人性的探讨本文中的观点大多来自于:(1)《全球通史》,斯塔夫里阿诺斯 著。(2)《万古江河》,许倬云 著。(3)《中国通史》傅乐成 著。此外,也夹杂着笔者自身的理解和认识,仅一家之言。本文着眼于世界历史而非仅仅中国历史,大概描述了一下人类的史前生活。人类的诞生首先得搞清楚“人类”指什么?(1)广义的人类:人科下的所有物种,有时也表示人属下的所有物种。包括智人。(2)狭义的人类:仅指智人(现代人类,
2022-03-21 00:30:35
5365
原创 实现C++变参模板函数和类
现在我们要实现一个函数,它可以接受任意个数、任意类型的入参,函数会依次打印出这些参数的值。使用c++的变参模板实现这个函数:void PrintArgs(){ std::cout << std::endl;}template <typename T, typename... Args>void PrintArgs(T t, Args... args){ std::cout << t << " "; PrintArgs(a
2022-03-18 20:54:30
1091
原创 模板的模板参数template template parameter
以Stack为例,一个普通的模板类:template <typename T>class Stack {public: void Push(T item); T Pop();private: std::vector<T> container_;};模板参数T表示Stack中保存的元素的类型,底层使用vector存储元素。如果我们想指定Stack里实际存储元素的容器类型,可以使用模板模板参数(template template paramete
2022-03-18 19:27:46
861
原创 什么是类成员指针
有下面一段C++代码:#include <iostream>class Node {public: int val_; Node *left_; Node *right_; Node(int val) : val_(val), left_(nullptr), right_(nullptr) {}};int main(){ int Node::* val = &Node::val_; Node * Node::* left =
2022-03-16 21:51:10
811
原创 【求解惑】变参函数模板出现segment fault?
在学习变参函数模板的时候,运行如下代码时,出现了段错误:tem.h#ifndef TEM_H#define TEM_H#include <set>#include <memory>#include <iostream>class Base {};class Derive1 : public Base {};class Derive2 : public Base {};class Derive3 : public Base {};class Mn
2022-03-15 23:31:21
449
原创 C++的左值和右值
C++里的表达式分为左值和右值,最初这是根据表达式在赋值运算=的左边还是右边区分的,但随着C++的发展,对左值右值的定义有了一些变化。一种说法是,左值表达式是可以取其地址的(使用&运算符);而右值表达式不行。现代C++中,对左右值有更复杂的分类:简单来讲,lvalue是左值(可对其取地址);xvalue和prvalue是右值。prvalue包括临时对象、非字符串常量的字面值等;xvalue包括std::move()的返回值等。对某个具体的类型X,X&只能接收左值,X&&
2022-03-11 23:39:58
1199
原创 什么叫依赖倒置
文章目录正向依赖双向依赖依赖倒置在一个复杂的软件架构里,为了方便软件的开发和维护,会把软件划分为多个模块,并进行分层。如下图所示,理想情况下:(1)模块B调用操作系统的接口,实现自己的功能,并提供API给模块A;(2)模块A调用模块B的API,实现自己的功能,并提供API给用户界面;(3)用户界面调用模块A的API,实现自己的功能,并提供API给客户;上面所说的“调用”是一种依赖关系。A需要调用B提供API才能完成自己的功能,称为A依赖B。上层软件和下层软件是相互的,比如A是B的上层,A是用
2022-03-06 11:40:55
4165
原创 【求解惑】C++ ->*是个什么操作
疑问如下:(1) left和right到底是个什么变量,为啥值会是1?它们和root变量有什么相同点和不同点?(2) 对root和left、right执行->*返回的是啥?是不是同时执行了operator->和operator*?为啥traverse最终返回的是指向4的节点的指针?
2022-03-05 10:40:44
453
1
原创 为什么模板的定义要和声明放在一起
对于一个普通的符号f,编译器对它做的事情如下:(1)编译时:包含f的定义(实现) 的源文件输送给编译器,编译器会编译相关代码并将结果打包到对应的.o里;(2)链接时:当某处需要使用符号f,便通过符号的声明寻找符号的实现,如果没找到某个符号的实现,就被报undefined错误。对于非模版的符号,编译器会如上正常执行。但对于模板类和模板函数,由于它的符号是抽象的,如f<T>(T)和A<T>::f()中的T是未知的。所以在(1)时不会把“符号”的实现打包到.o。(2)时,实例化模板时,编译器才会看到
2022-02-28 23:55:38
646
原创 机器字长、指令集字长和操作系统位数的关系
机器字长是CPU的位数,也是寄存器的宽度、数据总线的宽度,即CPU一次性最多能访问的数据的宽度。是硬件上的概念。计算机系统中指令集是对CPU的抽象。指令集字长体现了CPU开放能力的多少(对CPU能力利用的多少)。比如有一个64位的CPU,其寄存器宽度是64,但指令集字长为32,那么在程序运行(执行CPU指令)时,寄存器的高32位不参与运算或总是被置位0。指令集字长是软件上的概念。操作系统的位数等于指令集字长,决定了虚拟内存的大小和指针的长度。因此,机器字长 >= 指令集字长 == 操作系统位数
2022-02-28 22:02:44
2300
原创 前向兼容(forward)和后向兼容(backward)
因为翻译的原因,老是把前向兼容、后向兼容和forward、backward的对应关系搞不清,总感觉有些矛盾。
2022-02-28 21:22:23
5115
1
原创 为什么list不能使用全局sort函数
如果我们想给一个`list`排序,无法使用`C++`标准库中全局的`sort`函数,而要使用`list`自定义的`sort`函数。
2022-02-27 15:50:47
942
原创 【STL序列式容器】看看list的结构
与vector不同,list的底层是用双向链表实现的,其逻辑上连续的元素并不是地址连续的。list每插入或删除一个元素,就配置或释放一个元素的空间,内存利用率较高。对于任意位置上元素的插入或删除操作,永远是常数时间。vector的是O(n)。
2022-02-26 10:49:17
769
原创 【STL序列式容器】剖析vector
C++语言本身提供了一个序列式容器array,array是静态空间,一旦配置了就不能改变,类似于C语言的数组。vector的数据安排以及操作方式与array很像,但vector是动态空间,随着元素的加入,它的内部机制会自行扩充空间以容纳新元素。
2022-02-25 20:34:25
576
原创 【排序】选择排序和插入排序
文章目录排序算法相关接口选择排序插入排序排序算法相关接口排序关注的对象是数组元素(支持随机访问),每个元素都有一个key值,key值是能够按照某种方式排列(即可排序)的。一个排序算法大概需要实现如下接口:class SortFunc {public: void sort(Comparables a);private: bool less(const Comparable &a, const Comparable &b); void exch(Compar
2022-02-25 00:36:19
1070
原创 【空间配置器】内存基本处理工具
STL定义了五个全局函数,作用于未初始化的内存上。它们分别是construct()、destroy()、uninitialized_copy()、uninitialized_fill()和uninitialized_fill_n()。
2022-02-20 00:24:12
259
原创 【空间配置器】空间的申请和释放
文章目录两级配置器allocateSTL的实现有多个版本,其中SGI被GCC所采用。SGI属于open source的一员,但不属于GNU GPL。SGI STL的配置器的名称是alloc,每一个容器的实现都指定了其缺省的空间配置器为alloc。alloc不接受任何模版型别参数。template <class T, class Alloc = alloc>class vector { ... };C++的内存配置(申请)的基本操作是::operator new(),内存释放的基本操作
2022-02-19 21:09:03
226
原创 原来函数指针是这么声明的
文章目录今天看到了一个符号的声明,给我整懵了。void (* set_malloc_handler(void (*f) ())) ();经过一系列分析后,得出结论:set_malloc_handler是个函数,它的返回值和唯一的形参都是函数指针。要想知道一个符号到底表示的是指针还是函数,应该按优先级看离它最近的运算符是什么。函数调用()运算符的优先级高于解引用*。比如(*f)表示f是个指针,而它的类型声明为void (*)(),即函数指针,指向的函数的类型为void()(无返回值,无参数)。
2022-02-18 23:29:19
1169
原创 【并查集】union和find的几种实现
文章目录quick-find实现分析quick-union实现分析加权quick-union实现路径压缩的加权quick-union实现书接上回union-find算法(并查集),使用数组存储每个触点的分量标识,union和find有以下几种实现方式:(1) quick-find:find()的时间复杂度是O(1),union()的是O(n);(2) quick-union:find()的时间复杂度是O(n),union()的是O(1);(3) 加权quick-union:优化quick-union
2022-02-17 23:17:35
924
原创 【空间配置器】构造和析构
文章目录构造对象析构对象版本1版本2空间配置器为STL容器分配存储数据的空间,空间不一定是内存,也可以是磁盘或其它辅助存储介质。一般而言,我们所习惯的C++内存配置操作和释放操作是这样的:class Foo { ... };Foo *pf = new Foo;delete pf;这其中的new包含两步操作:(1)调用::operator new配置内存;(2)调用Foo::Foo()构造对象。delete也包含两步操作:(1)调用Foo::~Foo()将对象析构;(2)调用::ope
2022-02-16 20:21:13
480
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人