指针

【C++】如何接收函数return返回来的数组元素

て烟熏妆下的殇ゞ 提交于 2020-03-11 10:32:49
转自 https://www.cnblogs.com/Wade-James/p/7965775.html   我们知道return语句作为被调用函数的结束,返回给调用者函数值。一般来说,是返回一个函数值,像一个int, double,char等类型的数据,当然也可以是他们的指针。但是当我们遇到要返回很多数怎么办呢?通常想到的是以数组的形式返回,下面就让我们来看看:   通常来说有两种方式:1.通过返回传入数组指针的方式;2.以指针变量作为函数参数,来实现数组的返回。   一、返回传入数组指针的方式   首先我们来看看这种方法所涉及的知识:(1)指针函数。C语言中允许一个函数返回值是一个指针(地址)基本格式是: 基类型 * 函数名(参数列表)(2)静态变量与局部变量。我们知道C语言程序在运行时,操作系统会给其分配内存空间。这段空间主要分为四个区域,分别是 栈取,堆区,数据区,代码区 。那么 静态变量是存放在数据区,作用范围是全局的,在内存中只存储一份 。 局部变量通常放在栈中,随着被调用的函数的退出内存空间自动释放 。 要接收被调函数返回的指针,那么可以使用一个指针变量。关键是被调函数用什么去返回数组的首地址,正如前面所说,被调函数在执行完之后内存空间就被释放。   这里提供三种方法解决这一问题:    1)通过传入一个空的数组头地址,返回这个变量。 //通过返回传入数组的指针的方式

C++类的大小计算汇总

≯℡__Kan透↙ 提交于 2020-03-11 03:59:33
  C++中类涉及到虚函数成员、静态成员、虚继承、多继承、空类等。   类,作为一种类型定义,是没有大小可言的。   类的大小,指的是类的对象所占的大小。因此,用sizeof对一个类型名操作,得到的是具有该类型实体的大小。 类大小的计算,遵循结构体的对齐原则; 类的大小,与普通数据成员有关,与成员函数和静态成员无关。即普通成员函数、静态成员函数、静态数据成员、静态常量数据成员,均对类的大小无影响; 虚函数对类的大小有影响,是因为虚函数表指针带来的影响; 虚继承对类的大小有影响,是因为虚基表指针带来的影响; 静态数据成员之所以不计算在类的对象大小内,是因为类的静态数据成员被该类所有的对象所共享,并不属于具体哪个对象,静态数据成员定义在内存的全局区; 空类的大小( 类的大小为1 ),以及含有虚函数,虚继承,多继承是特殊情况; 计算涉及到内置类型的大小,以下所述结果是在64位gcc编译器下得到(int大小为4,指针大小为8); 一、简单情况的计算 #include<iostream> using namespace std; class base { public: base()=default; ~base()=default; private: static int a; int b; char c; }; int main() { base obj; cout<<sizeof

数据结构之单链表

放肆的年华 提交于 2020-03-11 02:22:50
顺序表之链接表示 概念:链接表示是实现线性表的另一种经常使用的存储结构。这种存储结构 不要求 逻辑关系上相邻的两个元素在 物理位置上也相邻存储 ,而是通过增加指针来表示元素之间的逻辑关系和后继元素的位置。 1. 单链表表示 单链表中的每个结点包括两个域:数据域(info)——存放元素本身的信息; 指针域(link)——存放后续结点的存储位置。 最后一个元素没有后继,它的指针不指向任何结点,成为空指针。^ NULL 每个结点只有一个指针域的链表叫单链表,指向链表中第一个结点的指针称为该链表的头指针。 做以下定义: struct Node ; //单链表的结点类型; typedef struct Node * PNode ; //指向结点的指针类型; struct Node { //单链表结点结构 DataType info ; PNode link ; } ; typedef struct Node * LinkList 假设llist是某单链表的头指针 加一个头结点会使得对单链表中的第一个结点进行处理时方便很多,具体内容下面会有提及。 2.单链表上运算的实现 1.创建空链表 LinkList createNullList_link ( void ) { LinkList llist = ( LinkList ) malloc ( sizeof ( struct Node ) ) ;

C++三大特性

青春壹個敷衍的年華 提交于 2020-03-10 23:58:03
封装继承和多态 封装:隐藏实现细节,使得代码模块化,封装就是把过程和数据包装,将客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操纵,对其他信息隐藏。 类继承是指C++提供来扩展和修改类的方法,类继承就是从已有的类中派生出新的类,派生类继承了基类的特性,同时可以添加自己的特性,继承又分为 单一继承 多重继承 菱形继承 多态是在具有继承关系的类对象中去调用某一虚函数时(使用基类的指针/引用去调用同一函数),产生了不同的行为,构成多态的条件有两个( 说白了就是通过指针/引用在不同时候调用同一函数可能调用的是不同的版本,多态是指接口的多种不同实现方式 ) 调用函数的对象必须是指针或者引用 被调用的函数必须是虚函数,且完成了虚函数的重写(不覆盖会调用派生类的函数吗?) 动态(类型)绑定/静态(类型)绑定 静态类型:对象在声明时的类型,其在编译时决定 动态类型:变量所指向内存中该对象的类型(通常指指针/引用所绑定对象的类型),在运行期决定 静态类型决定了某个函数能不能被调用,而动态类型则在动态绑定发生时决定调用该函数的哪个版本 如果不使用指针和引用,则静态类型和动态类型一定相同 静态绑定:也叫静态联编,绑定的是对象的静态类型,某特性(比如函数)依赖于对象的静态类型,发生在编译器 动态绑定:也叫动态联编,绑定的是对象的动态类型,某特性(比如函数)依赖于对象的动态类型

学习笔记:AC自动机

五迷三道 提交于 2020-03-10 18:35:31
这里的 \(AC\) 不要理解错啊...... 让一个文本串跑好多模式串的 \(KMP\) ,全称 \(Aho-Corasick\;automaton\) 很神奇, 就像面条机一样 。 将线形的字符串改成树形的 \(Trie\) 了,将令人懵逼的 \(next[]\) 数组改为难以理解的失配指针 \(fail\) 。 引用大佬 \(yyb\) 的话: \[Trie\text{树的失配指针是指向:沿着其父节点的失配指针,一直向上,直到找到拥有当前这个字母的子节点的节点的那个子节点}\] 再盗张图吧: 于是我们可以先建一颗平常的 \(Trie\) : 这里是结构体: struct node { int kid[28];//对应的儿子节点(a-0,z-25) int end,fail;//分别是有几个子串在此终结,fail指针 }ac[MAXN]; 插入操作(大家都会的) void add(char *s) { int len=strlen(s),u=0; for(int i=0;i<len;i++) { int j=s[i]-'a'; if(!ac[u].kid[j]) ac[u].kid[j]=++cnt; u=ac[u].kid[j]; } ac[u].end++; } 接下来就是寻找每个节点的失配指针了: 思路是这样的: 对于每个节点,枚举所有可能的儿子节点(a--z)

scanf与printf用法详解

ⅰ亾dé卋堺 提交于 2020-03-10 09:10:36
一、scanf家族 1、scanf家族的原型 int scanf(char const *format,...); int fscanf(FILE *stream,char const *format,...); int sscanf(char const *buffer,char const *format,...); 每个原型中的省略号表示一个可变长度的指针列表。从输入转换而来的值逐个存储到这些指针指向的内存位置。由于C的参数传递都是传值调用决定了可变参数都是指针列表。注意:若给的不是指针,而是变量值。scanf将把变量值当做指针,在进行解引用时或者导致程序终止,或者导致不可预料的内存位置的数据被改写。 2、返回值 当格式化字符串format到达末尾或者读取的输入不再匹配格式字符串所指定的类型时,输入就停止,并返回被转换的输入值的数目,若在任何输入都没被转换之前文件就到达尾部则返回EOF。 3、类型的匹配 由于scanf是采用可变参数的机制,所以函数无法验证它们的指针参数是否为正确的类型,所以函数假定它们是正确的,(因此格式字符必须和后面的指针指向的类型保持一致)如果指针参数的类型和输入数据的类型不匹配则结果值就是垃圾。而且邻近的变量也有可能被改写。例如: float a; scanf("%d",&a); //本来a是一个float数据,却用一个整形指针指向变量a。 4

C与C艹的内存管理方式

自古美人都是妖i 提交于 2020-03-10 08:57:12
  C 内存开辟出的空间一般可以分成: 代码段,数据段( 初始化的数据段, 为初始化的数据段BSS ),堆,栈   代码段 :保存程序文本,指令指针EIP就是指向代码段,可读可执行不可写   数据段 :保存初始化的全局变量和静态变量,可读可写不可执行   BSS :未初始化的全局变量和静态变量   堆(Heap) :动态分配内存,向地址增大的方向增长,可读可写可执行     栈(Stack) :存放局部变量,函数参数,当前状态,函数调用信息等, 向地址减小的方向增长 ,非常非常重要,可读可写可执行      最特别的是 栈stack ,它和别人是反着的!在Windows平台上,栈都是从上(高)向下(低)生长的!。   关于函数调用举个例子: int i= 0x22222222; char szTest [] = "aaaa";//a的ASCII码为0x61 func(i, szTest);   当访问进入func函数时,栈中的形式为(左侧地址 右侧数据):   0x0013FCF0 0x0013FCF8   0x0013FCF4 0x22222222   0x0013FCF8 0x61616161 PS: c++中语句解析顺序和函数调用时候顺序一致:由右向左! 比如如下语句,在输入vector为空时会造成 访问越界! void numIslands(vector<vector

new/delete和malloc/free

北城余情 提交于 2020-03-10 08:56:11
首先我们来谈谈malloc与free malloc和free是C函数库提供的两个函数,malloc从堆上(也叫自由存储区)分配一块合适的内存,程序返回一个指向这块内存的地址。free函数把它归还给内存池供以后使用。 注意的是这块内存并没有以任何形式进行初始化,如果进行初始化:要么自己动手进行初始化,要么使用calloc函数。 两个函数原型: void *malloc(size_t size); void free(void *pointer); malloc的参数就是需要分配的内存字节数(注意malloc不能自动计算字节大小,必须直接传字节数),如果内存池的内存满足这个需求,malloc就会返回一个指向被分配的内存块起始位置的指针;如果内存池为空或者不能满足你的分配需求,malloc将返回一个NULL指针( 这点很重要,每个从malloc分配的内存返回的指针用的时候都要检查是否为NULL )。 free函数的参数要么是NULL(不会产生任何效果),要么就是就是先前从malloc返回的值。只有这两种。释放一块内存的一部分是不允许的,动态分配的内存必须整块一起释放,但是有realloc的特性(缩小一块动态分配的内存),可以有效的释放他尾部的部分内存 注意观察的人会发现malloc返回的是一个 void*,那我们在内存上存储整数,浮点数和其他类型的时候该怎么办?

环形链表

假装没事ソ 提交于 2020-03-10 08:11:44
环形链表 描述 给定一个链表,判断链表中是否有环。 思路和代码 思路1:用一个哈希表,将每一个遍历到的节点加入哈希表中,如果遍历到节点已经出现在了哈希表中则证明有环. 思路2:一个指针走一步,一个指针走两步,若有环,则两个指针必会相遇. /** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; */ class Solution { public : bool hasCycle ( ListNode * head ) { ListNode * fast = head ; ListNode * slow = head ; while ( fast && fast - > next ) { slow = slow - > next ; fast = fast - > next - > next ; if ( fast == slow ) return true ; } return false ; } } ; 环形链表2 描述 在有环的基础上,返回入环的第一个节点 快指针和慢指针,快指针走两步,慢指针走一步,若相遇则有环 相遇之后,快指针返回head,慢指针在相遇这一点

【Leetcode】142.环形链表-ii(快慢指针)

不想你离开。 提交于 2020-03-10 06:22:41
题目链接 点击打开链接 题目描述 题解 是否是循环链表 使用 快慢指针法 ,慢指针一次走1个结点,快指针一次走2个结点,从头开始走会出现下面两种情况: 快指针变成 NULL ,说明链表不循环。 快慢指针相遇,说明链表循环,但循环节的起始位置未知。 注意这里快指针走的路程是慢指针走的路程的2倍。 找出循环节的起始位置 上一步相遇的位置是个关键,在这一结点上, 快指针走的路程 = 慢指针走的路程 * 2。 我们让一个指针从这个结点出发,另一个结点从开头出发,步长均为1,这两个指针 一定还会在这个位置相遇 。 那么它们在相遇前就会齐头并进一会,所以这两个指针在相遇的时候就是循环节的开始。 代码 /* * @lc app=leetcode.cn id=142 lang=cpp * * [142] 环形链表 II * * 思路:快慢指针法,快指针一次走2步,慢指针一次走1步。 * 如果快指针遇见NULL,表示无循环,否则总会相遇,这个时候,快指针的路是慢指针的2倍。 * 然后一个指针从慢指针开始,一个指针从开头开始,步长均为1, * 因为上一步相遇的位置快指针的路是慢指针的2倍,所以这么走下去两个指针一定会在同样的位置相遇。 * 既然会在同一位置相遇,且步长都为1,所以两者在进入循环结点的时候就一定相遇了。 * 这样就可以找到循环结点的位置啦。 * */ // @lc code=start