指针变量

指针学习四——指针、数组、地址

佐手、 提交于 2020-01-19 04:39:46
指针、数组、地址 指针是以地址作为值的变量,数组名的值是一个特殊的固定地址,看作是指针常量。 int a[100] , *p; 系统把编号为3000,30002...的内存字节作为数组元素a[0],a[1]...的地址。 基地址:内存位置3000是数组a的基地址,即a[0]的地址。 地址常量:数组名a是一个地址常量。 p=a; p=&a[0]; 语句等价,都把3000这个地址值赋给了指针p。 p=a+1; p=&a[1]; 同样,也是等价的,都把3002这个地址值赋给了指针p。 指针 内存地址 内存单元 数组元素 p 3000 a[0] p+1 3002 a[1] p+2 3004 a[2] 数组元素求和: 法一: sum=0; for(p=a;p<=&[99];p++) sum+=*p; *(a+i)与a[i]等价——地址+1为下一个地址,实际增加的不为一。 法二: sum=0; for(p=a;p<=&[99];p++) sum+=*(a+1); 法三: p=a; sum=0; for(i=0;i<100;++i) sum+=p[i]; 1.数组a是指针常量,不是变量。a++是非法的。 2.变量p是指向某个指定类型的指针,p+1代表访问的是下一个变量的内存地址。p+i是有意义的。 3.若p和q都是指向数组的指针,p-q产生一个int型的值,表示之间的数组元素的个数。 4

golang之不安全编程

无人久伴 提交于 2020-01-19 00:38:16
楔子 不安全编程?用golang以来也没发现有啥不安全的啊,而且golang有垃圾回收,也不需要我们来管理内存。当听到不安全编程这几个字,唯一能想到的也就是指针了,只有指针才可能导致不安全问题。我们知道golang中是有指针的,但是golang的指针并不能像C语言中的指针一样,可以进行运算,所以golang中的指针既提供了指针的便利性,又保证了安全。但是在golang中,可以通过一个叫做 unsafe 的包让指针突破限制,从而进行运算,一旦用不好会导致很严重的问题,但是用好了在某些场景下能够带来很大的便利,所以我们说这是不安全编程。但即便如此,我们还是可以使用的,而且golang的内部也在大量的使用unsafe这个包。 golang中的指针 尽管golang的指针没有C的指针那么强大,但是能够获取一个变量的地址,并且能通过地址来改变存储的值,我个人认为已经足够了。 package main import "fmt" func pass_by_value(num int){ num = 3 } func pass_by_pointer(num *int){ *num = 3 num = nil } func main() { num := 1 pass_by_value(num) fmt.Println("传递值:", num) //传递值: 1 pass_by_pointer(

C语言函数返回指针方法

那年仲夏 提交于 2020-01-19 00:10:27
什么是指针? 指针 是一个变量,其值为另一个变量的地址,即,内存位置的直接地址。 指针变量声明 type *var-name; type 是指针的基类型,它必须是一个有效的 C 数据类型, var-name 是指针变量的名称。用来声明指针的星号 * 与乘法中使用的星号是相同的。 空指针 赋为 NULL 值的指针被称为 空 指针,NULL 指针是一个定义在标准库中的值为零的常量。 数组指针: 它是一个指针,它指向一个数组。指向数组的指针,本质是指针。 int (*p)[3] 因为()优先级高,首先说明p是一个指针,指向一个int型的一维数组, 数组有3个元素,每个元素是一个int型整数 简单来说,就是int (*p)[3]是指一个指向数组的指针,它其实还是一个指针,只不过是指向数组而已 指针数组: 它是一个数组,数组的元素都是指针。存放指针的数组,本质是数组。 int *p[3] [ ] 优先级高,先与p结合成为一个数组,再由int*说明这是一个整型指针数组,指针数组本身就是个数组,只不过这个数组里存放的不是int 不是char,而是一个指针类型( int*,char* ),也就是就是地址 。 函数返回指针 C语言允许函数的返回值是一个 指针 (地址),我们将这样的函数称为指针函数。 用指针作为函数返回值时需要注意的一点是,函数运行结束后会销毁在它内部定义的所有局部数据,包括局部变量

C++ 智能指针详解

生来就可爱ヽ(ⅴ<●) 提交于 2020-01-18 22:44:49
C++ 智能指针详解 文章目录 C++ 智能指针详解 1. 智能指针能解决什么问题? 2. 智能指针的发展 3. 智能指针 shared_ptr 3.1 创建shared_ptr实例 3.2 访问所指对象 3.3 拷贝和赋值操作 3.4 检查引用计数 3.5 reset 函数 4. 智能指针 weak_ptr 4.1 weak_ptr 的基本用法 4.2 weak_ptr 的相关函数 4.3 weak_ptr 总结 5. 智能指针 unique_ptr 6. 智能指针注意事项 1. 智能指针能解决什么问题? 在C++中,动态内存的管理是通过一对运算符来完成的: new ,在动态内存中为对象分配空间并返回一个指向该对象的指针,可以选择对对象进行初始化; delete ,接受一个动态对象的指针,销毁该对象,并释放与之关联的内存。 动态内存的使用很容易出问题,因为确保在正确的时间释放内存是极其困难的。有时会忘记释放内存,在这种情况下会产生 内存泄露 ;有时在尚有指针引用内存的情况下就释放了它,在这种情况下就会产生引用非法内存的指针。 为了更容易(同时也更安全)地使用动态内存,C++11标准库提供智能指针(smart pointer)类型来管理动态对象。 智能指针的行为类似常规指针,重要的区别是它负责 自动释放所指的对象 。 智能指针是模板类而不是指针 。类似vector

c++ 指针(一)

依然范特西╮ 提交于 2020-01-18 19:02:31
指针 每一个变量都有一个内存位置 ,每一个内存位置都定义了可使用连字号( & )运算符访问的地址,它 表示了在内存中的一个地址 #include <iostream> using namespace std; int main () { int var1; char var2[10]; cout << "var1 变量的地址: "; cout << &var1 << endl; cout << "var2 变量的地址: "; cout << &var2 << endl; return 0; } 结果: var1 变量的地址: 0xbfebd5c0 var2 变量的地址: 0xbfebd5b6 一、定义 指针是一个变量,其值为另一个变量的地址 ,即, 内存位置的直接地址 。就像其他变量或常量一样,您必须在使用指针存储其他变量地址之前,对其进行声明。 type *var-name; 星号是用来指定一个变量是指针 int *ip; /* 一个整型的指针 */ double *dp; /* 一个 double 型的指针 */ float *fp; /* 一个浮点型的指针 */ char *ch; /* 一个字符型的指针 */ 所有 指针的值的实际数据类型 ,不管是整型、浮点型、字符型,还是其他的数据类型, 都是一样的,都是一个代表内存地址的长的十六进制数 。

考研之数据结构(第二章总结)

笑着哭i 提交于 2020-01-18 09:55:00
1.线性表:具有相同特性数据元素的一个有限序列,该序列中所含元素的个数叫做线性表的长度。 2.逻辑特性:线性表只有一个表头元素,只有一个表尾元素,表头元素没有前驱,表尾元素没有后继。 3.线性结构包括:线性表、栈、队列、串。 4.线性表的存储结构分为:顺序存储结构和链式存储结构。 5.顺序存储:把线性表的结点按逻辑顺序依次存放在一组地址连续的存储单元里。 特性:1.随机访问特性 2.占有连续的存储空间 3.做插入操作时要移动多个元素 6.链表:一种物理储存单元上非连续,非顺序的存储结构。 特性:1.不支持随机访问 2.结点的存储空间利用率较低 3.支持存储空间的动态分布 4.做插入操作时不需要移动元素 7.顺序表与链表各自的特点: 基于空间的比较:①.存储分配方式: 顺序表的存储空间是静态分配的(一次分配) 链表的存储空间是动态分布的(多次分配) ②.存储密度(存储密度=结点值域所占的存储量/结点结构所占的存储总量) 顺序表的存储密度=1 链表的存储密度<1(因为结点中有指针域) 基于时间的比较:①.存取方式:顺序表可以随机存取,链表只能顺序存取 ②.插入/删除时移动元素的个数:顺序表平均需移动近一半的元素,链表不需要移动元素,只需要修改指针。 8.插入一个元素时所需移动元素次数的期望值(平均次数):E=1/(n+1) ∑_(i=1)^(n+1)▒(n-i+1) =n/2

浅谈c语言的指针

≡放荡痞女 提交于 2020-01-18 05:12:14
对于非计算机专业的同学,c语言的指针往往就是老师的一句“指针不考“就带过了。c语言的指针号称是c语言的灵魂,是c语言中最精妙的部分。 指针本质上也是变量,也就是一段内存,只是他的特殊之处是他存储的数据是地址。地址又是什么概念?每一段内存都有其相应的地址,用街道来比喻的话,地址就是门牌号,数据就储存在家里。指针变量的作用就是储存门牌号。 定义一个指针变量要加一个*号。这里要提及两个概念,指针的类型和指针指向的类型。首先来说一下指针的类型。一般来说,指针类型要与指针指向的类型相匹配,不匹配的话往往会有警告。但是指针类型可以不匹配指针指向的类型。指针类型可以是用原本存在的类型如int *,char *,也可以自己定义,如结构体指针等。我认为定义指针类型目的就是确定指针的步长,即对指针变量进行p++操作时,p的数据加了几个字节。如int *p进行p++时,p的数据加了四个字节(对于32位系统),因为int型占的内存就是4个字节。所以同样的,char *p进行p++操作时,p的数据加了一个字节。同样的,定义一个占20个字节的结构体stu,那么stu *p的p++里面数据增加20个字节。所以就可以用char *p来访问int类型中每一个字节的数据。程序和运行结果如下: 所以可以通过这样的方法来访问int定义的i中每一个字节所存储的内容,也可以通过这样的方法确定大小端。

一款国产静态代码分析工具与Converity的对比

妖精的绣舞 提交于 2020-01-17 17:37:27
源伞科技Pinpoint,作为BAT都在使用的一款静态代码分析工具,到底有什么领先于其他厂商的能力? 1. 扩展和部署功能对比 源伞科技Pinpoint现有的检查器可以通过简单的json配置文件扩展业务逻辑。比如敏感数据泄露到日志检查器,企业或许有很多自己的日志打印函数,我们可以通过人工配置指定,即可提高检测质量。 如果不想人工配置,Pinpoint有未公开发布的库函数学习工具,可以通过线下分析企业代码库自动学习和生成上述配置文件。 Pinpoint对分布式多机扫描部署支持比 Coverity 好,并发扫描和结果合并x性能也比 Coverity 更强,能更好支持BAT级别的数千代码库扫描( 已在BT部署验证 )。 2. 分析能力对比 本节补充一些人工构造的例子介绍Pinpoint在分析能力上比Coverity强的部分。本节所有代码示例,Coverity均有误报或漏报。 Pinpoint更懂数据流 精确深度的指针分析,深入分析内存中的程序行为 高深度高精度函数调用链分析,查找跨越多层函数的深度问题 示例代码如下: (链接:https://www.sourcebrella.com/online-showcase/?id=5b483da03a21cd078346028f),此示例代码基于空指针(Null Pointer Dereference)问题检测。 准备代码:

C++堆指针栈指针

 ̄綄美尐妖づ 提交于 2020-01-17 16:51:22
C++堆指针栈指针 指针是一种灵活高效的内存访问机制。 按有无申请动态分配的方式,分为两种类别: 堆指针 、 栈指针 。 在程序中定义一个变量,它的值会被放入内存中。 如果 申请使用动态分配 ,它的值将放到 堆 中。 如果 没有申请动态分配 ,它的值将放到 栈 中。 tips:前提是定义了一个 空指针 。 1 、创建堆指针: 申请动态分配使用关键字 new 。 p = new type ; 其中,p表示指针,new是关键字,type是类型名。 new返回新分配的内存单元的地址。 指针函数: int * GetHeapsPoint ( int * p ) { p = new int ; //申请动态分配,令指针指向某个int型 int k1 = 111 ; * p = k1 ; //指向k1 return p ; } 可以看到指针p创建后申请了动态分配,程序自动交给他一块堆地址。 2 、创建栈指针: 指针函数: int * GetStackPoint ( int * i ) { int k2 = 222 ; i = & k2 ; //无动态分配,直接指向k2的地址 return i ; } 可以看到指针i则是获取了栈中k2的地址,属于静态分配。 3、动态内存的销毁: 动态分配方式虽然灵活,但是随之带来新的问题。申请一块堆内存后,系统不会再程序执行时依据情况自动销毁它。 若想释放该内存

引用 & 指针区别* int &a=b

落爺英雄遲暮 提交于 2020-01-17 10:12:25
参数里面的&表示引用型参数 一般的参数传递的时候,形参是实参的副本,也就是说,形参虽然和实参一样,但是在内存中的位置不同 而引用型参数,在函数参数传递的时候,并不要复制参数,形参和实参在内存中是同一个位置,因此修改形参,实参也变化了 & 这里表示引用,说明需要传递变量给这个函数,函数中可以对参数的值进行修改 如果没有 &,修改的就是函数体中的临时变量 ———————————————— 原文链接:https://blog.csdn.net/Faracall/article/details/88621633 类型标识符 &引用名=目标变量名 # include <iostream> using namespace std ; int main ( ) { int num1 = 1 , num2 = 2 ; int & ref1 = num1 , & ref2 = num2 ; ///引用必须要初始化 cout << "num1 = " << num1 << ",num2 = " << num2 << endl ; cout << "ref1 = " << ref1 << ",ref2 = " << ref2 << endl ; ///修改引用的值将改变其所绑定的变量的值 ref1 = - 1 ; cout << "num1 = " << num1 << ",ref1 = " <<