指针变量

数组与链表

时光毁灭记忆、已成空白 提交于 2020-01-25 12:11:29
引子 假设你去看演出,需要将东西寄存。寄存处有一个柜子,柜子有很多抽屉。 计算机就像是很多抽屉的集合体,每个抽屉都有地址。 fe0ffeeb是一个内存单元的地址。 需要将数据存储到内存时,你请求计算机提供存储空间,计算机给你一个存储地址。需要存储多项数据时,有两种基本方式——数组和链表。但它们并非都适用于所有的情形,因此知道它们的差别很重要。接下来介绍数组和链表以及它们的优缺点。 数组 有时候,需要在内存中存储一系列元素。假设你要编写一个管理待办事项的应用程序,为此需要将这些待办事项存储在内存中。 我们先将待办事项存储在数组中。 使用数组意味着所有待办事项在内存中都是相连的 (紧靠在一起的)。 现在假设你要添加第四个待办事项,但后面的那个抽屉放着别人的东西! 这就像你与朋友去看电影,找到地方就坐后又来了一位朋友,但原来坐的地方没有空位置,只得再找一个可坐下所有人的地方。在这种情况下,你需要请求计算机重新分配一块可容纳4个待办事项的内存,再将所有待办事项都移到那里。如果又来了一位朋友,而当前坐的地方也没有空位,你们就得再次转移!真是太麻烦了。同样,在数组中添加新元素也可能很麻烦。如果没有了空间,就得移到内存的其他地方,因此添加新元素的速度会很慢。 再以整型数组为例,数组的存储形式如下图所示。正如军队里的士兵存在编号一样,数组中的每一个元素也有着自己的下标,只不过这个下标从0开始

【C++】构造函数和this指针

只愿长相守 提交于 2020-01-25 10:28:49
通常this指针在对象构造完毕后才完全生成,而在构造函数执行过程中,对象还没有完全生成,所以this指针也是没有完全生成的,在构造函数中使用this指针会存在问题,应该尽量避免。 构造函数中可以访问对象中已经初始化的成员(成员初始化是有顺序的),但尽量不要调用对象方法,因为调用方法的时候会隐含使用this指针。 在某些应用中会存在这样的对象,他的成员变量需要用对象的this指针进行初始化: class A { B b; }; class B { A* a; }; A类的构造函数可以写成: A(): b(this) 这样会违反构造函数中尽量不使用this指针的规范,一种替代的方法是,在A类中增加Init方法,在此方法中设置B的成员变量值为A对象的this指针,Init方法在A对象构造完后调用,从而this指针是完整的: class A { B b; A() { } void Init() { b.SetMemberA(this); } }; class B { A* a; void SetMemberA(A* pa) { a = pa; } }; 来源: CSDN 作者: 摩羯座程序员 链接: https://blog.csdn.net/qq_43248127/article/details/103772795

数据结构线性表3---单链表

大城市里の小女人 提交于 2020-01-25 04:55:33
今天我说的内容是单链表,所以提前来No pic say a J8 环节! 其实大家都知道,单链表就是我们所说的链式存储结构当中最简单,也是最重要的一个内容。 所以单链表的图形描述就是下图。 先别着急,看不懂也别慌。我先说几个注意事项,再给你细细道来。 1.头指针:是指链表指向第一个结点的指针,若链表有头结点(注意也就是说头结点不一定要有),则是指向头结点的指针。 2.头指针的作用:具有标识作用,所以常用头指针冠以链表的名称(指针变量的名字) 3.无论链表是否为空,头指针均不为空 4.头结点是为了操作的统一和方便设立的,放在第一个有数据“真”元素结点之前,其数据域一般无意义(但也可以用来存放链表的长度) 5.有了头结点,对在第一个接结点前插入结点和删除第一个结点操作与其他结点的操作就统一了。 7.对数据元素ai来说,除了存储其本身的信息外,还需要存储一个指示其直接后继的信息(即直接后继的地址) 8.空链表 所以接下来看看单链表的结构体定义吧 define ElemType int typedef struct LNode { ElemType data; struct LNode *next; }LNode;//取别名 typedef struct LNode *LinkList;//取别名 结构体两个别名 其实啊,线性表1看的认真的同学这个结构体,但是跟顺序表不同在于

数据结构之链表

雨燕双飞 提交于 2020-01-25 04:46:34
数据需要一块连续的内存空间来存储,对内存的要求比较高。而链表恰恰相反,它并不需要一块连续的内存空间,它通过“ 指针 ”将一组 零散 的内存块串联起来使用。 最常见的链表:单链表、双链表、和循环链表。 单链表 结点 :除了存储数据之外,还要记录链上的下一个节点的地址,如下图,我们把这个记录下个结点地址的指针叫作 后继指针 next 头结点 :用来记录链表的基地址。 尾结点 :指向一个空地址 NULL 针对链表的插入和删除操作,只需考虑相邻结点的指针改变,所以对应的时间复杂度是O(1)。 链表想要随机访问第k个元素,就没有数组那么高效,链表的数据并非连续存储的,所以无法像数组那样,根据首地址和下标通过寻址公式就能直接计算出对应的内存地址,而是要根据指针一个结点一个结点的一次遍历,直到找到相应的结点。需要 O(n)时间复杂度 。 循环链表 是一种特殊的单链表。它和单链表唯一的区别就在尾结点。循环链表的 尾结点指针是指向链表的头结点 。 当处理的数据具有环形结构特点时,就特别适合采用循环链表。 双向链表 双向链表支持双向遍历,它需要额外的两个空间来存储后继结点和前驱结点的地址。 时空替换思想 :“用空间换时间” 与 “用时间换空间” 当内存空间充足的时候,如果我们更加追求代码的执行速度,我们就可以选择空间复杂度相对较高,时间复杂度小相对较低的算法和数据结构,缓存就是空间换时间的例子

C语言文件操作总结

泪湿孤枕 提交于 2020-01-25 01:22:24
文件的打开操作 fopen 打开一个文件,操作文件指针FILE *       文件的关闭操作 fclose 关闭一个文件       文件的读写操作 fgetc 从文件中读取一个字符               fputc 写一个字符到文件中去               fgets 从文件中读取一个字符串               fputs 写一个字符串到文件中去               fprintf 往文件中写格式化数据               fscanf 格式化读取文件中数据               fread 以二进制形式读取文件中的数据               fwrite 以二进制形式写数据到文件中去               getw 以二进制形式读取一个整数               putw 以二进制形式存贮一个整数     文件状态检查函数 feof 文件结束               ferror 文件读/写出错               clearerr 清除文件错误标志               ftell 了解文件指针的当前位置       文件定位函数 rewind 反绕               fseek 随机定位 一、文件打开关闭 (一)文件打开  1. 函数原型 FILE *fopen(char

C语言指针笔记一

假装没事ソ 提交于 2020-01-25 00:45:23
其实以前在学校也学过一点点C,不过那都是好久之前的事情了。最近因为要上 C++ 的课程,所以必须要熟练C基础,指针又要重新复习一遍了。 下面这幅图很简单的表现了变量和指针的关系 指针变量p也是在内存中占用了地址的,通过&p可以获取到 其实可以很形象的表示:*p是连接变量a的桥梁,有了这个链接,我们就可以访问到变量a的内容:*p = a,而变量p本身存放的是a的地址。 来源: CSDN 作者: 风楚颜 链接: https://blog.csdn.net/maybe_frank/article/details/103835499

C语言指针

此生再无相见时 提交于 2020-01-25 00:32:54
指针 指针 指针变量的定义语法 取地址运算符:& 间接运算符:* 空指针 void指针 malloc函数 const 常量指针 常量指针 常量指针变量 指针常量 指针与数组 通过指针变量访问数组 数组指针 指针数组 指向函数的指针(函数指针) 指针 指针 就是内存地址,指针变量就是存储地址的变量. 作用: 使用指针可提高程序的编译效率和执行速度,是程序更加简洁;通过传递指针参数,使被调用函数可向主调函数返回除正常的返回值之外的其他数据,从而达到两者之间的双向通信;还有一些任务,如动态内存分配,没有指针是无法执行的;指针还用于表示和实现各种复杂的存储结构(如链表),从而为编写出更高质量的程序奠定基础;利用指针可以直接操纵内存地址,从而可以完成和汇编语言类似的工作. c语言提供 两种指针运算符 : * 和 & . 指针变量的定义语法 指针变量的定义语法: 数据类型 * 变量名 [ = 初值 ]; 指针变量定义时,数据类型并不是指指针变量的数据类型,而是其所指目标对象的数据类型.例如: int* p ;定义 p 是指针变量,可以存储 int 型变量的地址,p 变量的类型是 int*,而不是 int.这是告诉编译器, p 变量只能存储整型变量的空间地址,不能存储其他类型空间的地址 取地址运算符:& p = &a; 表明得到整型变量 a 的地址,并把该地址存入指针变量 p 中

Berry 实现:自动扩充的调用栈

末鹿安然 提交于 2020-01-24 23:09:55
概述 调用栈用于存储函数执行过程中调用链上所有函数的局部变量等调用信息。Berry 调用栈特指脚本程序的调用栈,而不是 C 的调用栈。 在 be_vm.h 中可以看到 VM 结构中和调用栈相关的字段: struct bvm { // ... bvalue *stack; /* stack space */ bvalue *stacktop; /* stack top register */ bstack callstack; /* function call stack */ // ... }; stack 和 stacktop 用于维护存储局部变量的栈(以下简称“变量栈”,函数的栈空间指 vm.stack 中被该函数使用的一段空间),而 callstack 为函数栈帧的堆栈。 我们用一个简单的脚本来说明上述字段的作用: def func1(c) return c + 1 end def func2(b) return func1(b) + 2 end def func3(a) return func2(a) + 3 end 当我们执行 func3(10) 的时候,执行到 func1 内部时调用链最长: call stack top +-------------------------+ | function: func1 | | local variable(s): c | +-

coursera学习——指针

廉价感情. 提交于 2020-01-24 22:40:47
一、一位数组与指针 1.变量三要素:地址(指向这个变量的指针)、值、名字。 2. &:取变量的地址 int a = 0 ; cout << & a ; //打印a变量起始地址(a的地址为4B,即地址长度、指针为4B) 3.*:取指针(地址)的值 cout << * & c ; //取地址为&c的变量的值(*&c=c) 4.指针变量:存放指针(地址)的变量 int * pointer = NULL ; //赋初值 //指针变量的定义,pointer指向的c为int型,因此*pointer为int型 pointer = & c ; //pointer指向c(或者直接定义 int *p=&c) pointer变量值为c变量的地址 //*pointer=c 5.运算:高(只低于a+±-) int * p = NULL ; ( * p ) ++ ≠ * p ++ ( 原来指向 0x0012FF71 , ++ 后指向 0x0012FF75 , int 为加 4 , char 为加 1 ) 6.数组 int a [ 5 ] = { 0 } ; //数组名=指向数组第一个元素的指针 int * p = & a [ 0 ] ; //a++无意义 p++有变化,p可以指向数组元素外的元素 二、字符串与指针 1.定义 char a [ 10 ] ; char * p ; p = a ; /

C++函数指针总结

巧了我就是萌 提交于 2020-01-24 07:05:14
  学习c++的过程中,指针是难点,熟悉了指针之后,还有一个让人很蛋疼的难点,那就是函数指针了。本博文详细介绍一下常见的各种坑爹的函数指针。   至于指针的详细学习,推荐这篇博文 C++指针详解   与数据一样,函数也有地址,函数的地址就是内存中存放函数语言代码的起始地址。函数指针就是指向这个地址。函数指针所指向的类型,就是函数本身。我们知道,指针所指向类型代表了指针所指向的内存区域的大小。所以函数指针所指向的类型,就是函数在内存中所占据内存的大小。知道了函数的起始地址和大小,所以函数指针可以很轻易的代替函数完成函数调用。 一、最简单的函数指针   变量都包括声明和赋值,指针不例外,函数指针也不例外。我们来看一个简单的函数: void add(int a, int b){ cout << a + b << endl; }   一个简单的加法计算并输出到命令行的函数。   那么如何通过函数指针来调用它呢?   1、声明: void (*p1)(int a, int b);   函数指针的声明很简单,基本就是通过一个指针把函数名替换。指针p1的类型为void (*) (int a,int b),表明指针是一个指向某个函数的指针,指针指向的类型为void () (int a,int b)   2、赋值: p1 = add;   3、也可以直接定义: void (*p1)(int a,