指针

redis 系列7 数据结构之跳跃表

我怕爱的太早我们不能终老 提交于 2020-02-04 20:26:36
原文: redis 系列7 数据结构之跳跃表 一.概述    跳跃表(skiplist)是一种有序数据结构,它通过在每个节点中维持多个指向其他节点的指针,从而达到快速访问节点的目的。在大部分情况下,跳跃表的效率可以和平衡树(关系型数据库的索引就是平衡树结构)相媲美,并且因为跳跃表的实现比平衡树要来得更为简单,所以有不少程序使用跳跃表来代替平衡树。   Redis使用跳跃表作为"有序集合键"的底层实现之一,如果一个有序集合包含的元素数量比较多,又或者有序集合中元素的成员是比较长的字符串时,Redis就会使用跳跃表来作为有序集合键的底层实现。   下面用到的命令zadd和zrange。 使用zadd 命令将多个成员(number)及其score值加入到有序集key中。number是有序集成员,score可以是整数值或双精度浮点数。使用zrange命令将返回有序集合中给定区间的元素,start从0开始,stop 结束下标。 -- zadd命令语法格式 ZADD key score member [[score member] [score member] ...] -- zrange命令语法格式 ZRANGE key start stop [WITHSCORES]   例1:下面使用zadd将fruit-price作为一个有序集合键,每个节点元素包括score和number。其中

指针变量、普通变量、内存和地址的全面对比

邮差的信 提交于 2020-02-04 20:02:25
本篇文章,将提到4个概念: 1、普通变量 2、指针变量 3、内存(内存空间) 4、地址 我们先看内存是什么?内存是实实在在的硬件,可以存放数据!在我们的一块可编程的芯片的内部有大把的内存。 形象一点,内存就像一个个的小格子,每个格子的大小是一个字节,可以存放一个字节的数据。 那这么多内存如何区分呢?那就得靠地址。地址是内存的标识,每一个地址都对应一个内存。所以内存和地址是一一对应密不可分的。 接着看,什么是普通变量? 如 char a; 就是一个普通变量。普通变量a其实是语言本身创造了,是为了更方便的表示内存。我们对a进行访问其实就是直接对内存进行访问。至于a表示的内存的地址是多少,程序员一般不用关心。编译器会自动分配地址,也就是常说的为a分配一个地址。如果想知道a的地址也可以通过&a得知。 再看指针变量,他和普通变量的区别在于,普通变量是和一块内存空间关联。而指针变量却是和两块内存空间想关联: 1、保存指针变量本身的空间,这个空间大小是固定的,32位系统中是4个字节。 2、指针指向的内存空间。 如char* a; 指针变量a,他本身需要一个空间,也就是上面说的(1)。 而(1)这个空间存放的内容是另一个内存空间的首地址。指针变量可以通过改变自己去访问其他地方的内存空间。 如果说普通变量有两种形态: 1、a 表示一块内存空间 2、&a 表示当前内存空间的地址

发一篇关于 数组名称 和 指针区别 的专题探讨

99封情书 提交于 2020-02-04 20:01:11
char p_arr[] = " p_arr : hello world " ; 声明一个数组时,编译器将根据声明所指定的元素数量为数组保留内存空间,然后再创建数组名,它的值时一个常量 ,指向这段空间的起始位置。 数组名是符号地址常量 ( 一个常量指针,这个值不能被改变 ) ,在编译时求值并存在编译器的符号表里面,其值就是个内存地址;所以可以认为程序没有给他分配空间,数组名只是代表了那个数组空间; 与指针不一样,指针指向一块空间, 同时指针本身也存储在某个空间 ;可以认为数组名存在在符号表里,符号表是编译器用的,我们管不到;p_arr和&p_arr值是一样的,本来对常量取地址是非法的,但是标准组织没有定对数组名取地址是非法还是合法,所以因编译器而异. 引用chinaunix上一个叫dump_crash会员的发言: C专家编程里解释的很好: 经典的错误:在一个文件定义了数组,却在另外一个文件声明其为指针。代码如下: /*File name: main.c*/ extern int* array; /*声明指针*/ int main(void) { array[0]=1; /*用指针访问数据*/ return 0; } /*File name: def.c*/ int array[5]={0}; /*定义的却是数组*/ 1。编译器对数组名和指针变量的处理方式

python文件的打开与关闭

风格不统一 提交于 2020-02-04 17:32:00
1 #文件的打开 2 #open(文件名,访问模式) 3 f=open('test.txt','w') 4 #文件的关闭 5 f.close() 访问模式 说明 r 以只读方式打开文件。文件的指针将会放在文件的开头。这是默认模式。 w 打开一个文件只用于写入。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。 a 打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。 rb 以二进制格式打开一个文件用于只读。文件指针将会放在文件的开头。这是默认模式。 wb 以二进制格式打开一个文件只用于写入。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。 ab 以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。 r+ 打开一个文件用于读写。文件指针将会放在文件的开头。 w+ 打开一个文件用于读写。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。 a+ 打开一个文件用于读写。如果该文件已存在,文件指针将会放在文件的结尾。文件打开时会是追加模式。如果该文件不存在,创建新文件用于读写。 rb+ 以二进制格式打开一个文件用于读写。文件指针将会放在文件的开头。 wb+

两数之和2:输入有序数组(leecode)(c++)

廉价感情. 提交于 2020-02-04 12:28:45
在一个有序数组中,找出两个数,使得两数之和等于目标值。数组下标从1开始。 输入: numbers = [5,6,7,8,9,10], target = 11 输出: [1,2] 解释: 5 与 6 之和等于目标值 11 。因此 index1 = 1, index2 = 2 。 1.1解题思路 有三种常见解法,一种是暴露和哈希表,可以参考博主写的这篇博客 https://blog.csdn.net/naibozhuan3744/article/details/104160305 。本文主要总结用双指针法,解决这个问题。因为这是一个有序数组,所以可以用双端指针,分别取数据,具体步骤如下: 1.1.1双端指针指向数组起始pstart和末尾位置pend 1.1.2如果这两个指针指向的数相加和为目标值,则顺序输出;否则继续比较 1.1.3如果两数之和小于目标值,则指向较小值的指针*pstart向前移动,直到找到满足目标值的两数为止; 1.1.4如果两数之和大于目标值,则指向较大值的指针*pend向左移动,直到找到满足目标值的两数为止。 1.2代码如下 1.2.1双指针解法(4ms,9.7MB) #include <iostream> #include <vector> #include <map> #include <iterator> using namespace std; /

c语言函数指针

人盡茶涼 提交于 2020-02-04 11:26:13
1.在讲这个问题之前,我们要明白一个问题。就是我们为什么要把一个函数的地址作为参数传递给另一个参数。要知道在C语言中,一个函数内部是可以直接调用其他函数的,既然可以直接调用,为什么还要用这么麻烦的办法去把函数当做参数来传递呢。下面我举个例子。 例如我们设计一个estimate() 的函数计算一个程序运行的时间,但不同的人估算时间的时候可能算法有所不同,算出的时间也应该不同。但我们都调用同一个estimate() 函数,现在该怎么办呢,重写estimate() 函数固然是一个办法,但是我们还有另外的办法,比如我们 把estimate()函数中计算时间的算法作为一个公共变量让其作为参数传入 ,我们只需要把 各自的计算时间的算法写成一个函数,再通过参数传递给estimate() ,而estimate()中的内容还是原来的不变,这样就可以实现不同的人计算出来的时间不同了。 2.既然知道了函数参数传递的用处,那么我们现在就来说一下它的用法。 首先参数传递分为两种,一种是 值传递 ,一种是 地址传递 。 一般我们传递时用的是地址传递。因为,若是采用值传递的话,比如我们传递一个数组 double a[100] ,则在调用函数的时候。编译器会 把这整个数组复制到函数中 ,这样使用的空间是 100*sizeof(double)=800 .若是我们只传递 数组名 a 这个地址 的话

AJ整理问题之:内存堆栈

谁说胖子不能爱 提交于 2020-02-04 05:47:49
内存 数据在内存中的存放 在计算机中,运行的应用程序的数据都是保存在内存中的。 不同类型的数据,保存的内存区域不同,其中包括: 1:栈区(stack)由编译器自动分配并释放,一半存放函数的参数值,局部变量等。 2:堆区(heap)由程序员分配和释放,如果程序员不释放,程序结束时,可能会由操作系统回收。 3:全局区(静态区)全局变量和静态变量的存储是放在一起的,初始化的全局变量和静态变量存放在一块区域,未初始化的全局变量和静态变量在相邻的另一块区域,程序结束后由系统释放。 上面三个很重要,下面三个了解 4:文字常量区:存放常亮字符串,程序结束后由系统释放。 5:程序代码区:存放函数的二进制代码。 6:寄存器去:用来保存栈顶指针和指令指针(我们基本用不到。。。)。 栈内存区中得数据 栈区内存是压栈的讲究 特点:先进后出。 系统给自动回收。 由系统自动分配,速度较快。但程序员是无法控制的。 int sum(int x, int y) { NSLog(@"x: %p, Y: %p", &x, &y); int result = x + y; NSLog(@"%p", &result); return result; } void demo1() { // 在栈区中的变量,i本质上对应"内存地址"的"标签" // 指针 * 表示指向内容空间的内容 & 表示地址 int i = 10; i =

堆和栈的概念

十年热恋 提交于 2020-02-04 05:45:50
数据在内存中的存放 在计算机系统中,运行的应用程序的数据都是保存在内存之中。 不同类型的数据,保存的内存区域不同,其中包括: 1.栈区:(stack)由编译器自动分配并释放,一般存放函数的参数值,局部变量等。 2.堆区:(heap)由程序猿分配和释放,如果程序猿不释放,程序结束时,可能由操作系统回收。 3.寄存器区:用来保存栈顶指针和指令指针。 4.全局区(静态区):全局变量和静态变量的存储是放在一起的,初始化的全局变量和静态变量存放在一块区域,未初始化的全局变量和静态变量在相邻的另一块区域,程序结束后由系统释放。 5.文字常量区:存放常量字符串,程序结束后由系统释放。 6.程序代码区:存放函数的二进制代码。 栈区中的数据 应用程序启动后,操作系统会为应用程序在栈区开辟内存空间,用于存放局部变量,以及函数的参数等。 iOS主线程栈区大小为1M,MAC主线程栈区大小为8M. 栈区中的变量由编译器负责分配和释放。 栈区中的数据是以“栈”的形式管理的,先进后出(FIBO)。 访问栈区中变量的效率高,不会出现内存碎片。 栈区中的变量名(不带*)相当于是指向栈区数据的指针别名,变量名可以简化程序员的工作。 栈中地址是从高地址——>低地址。 堆中的数据 由于栈区的空间有限,iOS的应用程序中,对象都是建立在堆中的。 堆区包括系统内存和虚拟内存(硬盘内存),由所有正在运行的应用程序共享使用。

iOS 内存管理

℡╲_俬逩灬. 提交于 2020-02-04 03:58:51
本篇随笔记录的是看唐巧写的「iOS开发进阶」书籍的「理解内存管理」知识点汇总,这里分享给大家。 Objective-C 和 Swift 语言的内存管理方式都是基于引用计数「Reference Counting」的,引用计数是一个简单而有效管理对象生命周期的方式。引用计数分为自动引用计数「ARC: Automatic Reference Counting」和手动引用计数「MRC: Manual Reference Counting」,现在都是用 ARC 了,但是我们还是很有必要了解 MRC。 1. 引用计数的原理是什么? 当我们创建一个新对象时,他的引用计数为1; 当有一个新的指针指向这个对象时,他的引用计数就加1; 当对象关联的某个指针不再指向他时,他的引用计数就减1; 当对象的引用计数为0时,说明此对象不再被任何指针指向,这时我们就可以将对象销毁,回收内存。 由于引用计数简单有效,除了 Objective-C 语言外,Microsoft 的 COM「Component Object Model」、C++11(基于引用计数的智能指针 share_prt)等语言也提供了基于引用计数的内存管理方式。 举个例子: 新建工程,Xcode 默认开启的是 ARC,我们这里针对「AppDelegate.m」文件使用 MRC,进行以下配置: 选择目标工程,然后在「Build Phases」的

IOS 内存管理

我只是一个虾纸丫 提交于 2020-02-04 03:03:11
小议iphone内存管理与属性 一、前言 对于大多数从C++或者JAVA转过来学习Object-C(以下简称OC)的人来说,OC这门语言看起来非常奇怪,用起来也有点麻烦。 OC没有像JAVA一样的垃圾回收机制,也就是说,OC编程需要程序员手动去管理内存。这就是为什么它烦的原因,苹果却一直推崇开发者在有限硬件资源内写出最优化的代码,使用CPU最少,占用内存最小。 二、基本原理 对象的创建: OC在创建对象时,不会直接返回该对象,而是返回一个指向对象的指针,因此出来基本类型以外,我们在OC中基本上都在使用指针。 ClassA *a = [[ClassA alloc] init]; 在[ClassA alloc]的时候,已经发送消息通知系统给ClassA的对象分配内存空间,并且返回了指向未初始化的对象的一个指针。 未初始化的ClassA对象接手到init消息,init返回指向已初始化后的ClassA对象的一个指针,然后将其赋值给变量a。 在创建并使用完一个对象的时候,用户需要手动地去释放该对象。 [a dealloc]; 如果指针a和b同时指向堆中同一块内存地址 ClassA *a = [[ClassA alloc] init]; ClassA *b = a; [a dealloc]; 当执行到第三行的时候,指针b就成了无头指针。这是一个在C++中也是常见的错误,我们需要避免这类错误