C/C++指针入门(自用笔记)

C/C++指针入门(自用笔记) 自学笔记不喜勿喷如有错误欢迎指正文章目录运算符名称运算符的其他含义复用*地址运算取地址解引用*理解指针的定义与运算指针的定义指针的运算加运算new关键字分配内存Cnewdeletenew与动态数组这部分之后再写数组与指针1、数组的指针表示方法2、对数组名取地址运算符名称在地址运算中表示取地址寻址取址*表示解引用当然在程序运行中这两种运算符也存在复用的情况运算符的其他含义复用1、按位与两个与连起来是条件与eg0101000100012、引用在C当中就是给变量取别名eginta10;intrefa;// ref是a的引用ref20;// 修改ref等同于修改a// 此时 a 20*乘法运算地址运算取地址inta10;int*ba;coutaendl;coutbendl;运行结果100x8f036e75a466在这里10就a存储的值0x8f036e75a466就是a在内存当中的地址解引用*需要注意的是*在声明/定义中和运算中的含义不同inta10;int*ba;coutaendl;cout*bendl;运行结果1010理解取地址与解引用*二者互为逆运算取地址可以理解为这间房子里面住着我大舅我要知道我大舅家的地址解引用*可以理解为我知道我二舅家的地址我去找我二舅指针的定义与运算指针的定义对于个人习惯而言我更喜欢如下的方式int*ba;但实际上int【空格】*【空格】b之间的空格是随意的也就是说也可以是如下的形式int*ba;int*ba;int*ba;理解int*可以看作一个整体表示int类型的指针int*ba;也可以这么理解但我觉得这么理解有一个小bugint看作整型类型b表示对b进行解应用也就是b这个地址所对应的解应用的数据是int。 但这么理解无法解释将a赋给bcpp int *ba;需要注意的是int类型的指针这一概念不是说这个指针的存储类型是int在内存当中所占的空间而是指所存储的这个地址地一个属性。举例int*ba;char*dc;在这里b是int类型的指针其存储a的地址对于a而言a的存储占4个字节也可能是两个具体根据系统定比如在单片机中就是2个字节对于b来说b0x8f036e75a466的存储占6个字节而d是char类型的指针其存储c的地址对于c而言c的存储占1个字节对于d来说d0x8f036e75a46a的存储占6个字节也就是说指针的类型这个概念只是属性并不代表实际的存储空间指针的存储空间是由内存容量决定的整个内存有多少地址需要多少位来进行寻址则指针的存储就占几位。那可能有人就要问了既然指针的存储空间是一定的并且在不同的主机上占的不一样为什么还要在声明/定义的时候来规定他的类型呢为什么要赋予他这种属性呢这就体现在指针的运算上了指针的运算对于指针而言其运算只有两种一种是加另一种是减对地址的乘除是没有意义的。加运算还是上面的例子int*ba;b;char*dc;d;b0x8f036e75a466“属性”int4字节自加一之后变为0x8f036e75a46640x8f036e75a46ad0x8f036e75a46a“属性”char2字节自加一之后变为0x8f036e75a46a20x8f036e75a46c总结将指针变量加一后其增加的值等于指向类型占用的字节数。new关键字分配内存Cnew在c当中使用malloc来分配内存小白可能不太知道这个函数实际上这个函数也包含在stdio.h当中也就是说和一开始咱们最一开始使用的printf这个函数是一个地位。在C中分配内存被定义成了关键字new。举例int*pnewint;运行过程我们告诉new我们需要的内存大小要四个字节也就是intnew为我们在堆区找到一块合适的内存大小并返回他的地址。返回的地址被我们付给指针p。需要注意的是使用new分配的内存是没有名称的只能通过指针来进行访问。什么叫没有名称呢还是上面的例子。inta10;int*ba;a就是存储这个内容为10的内存的名称我们可以通过a这个变量名或者是*b对指针解应用的方式来访问这块内存。需要注意的是这里创建的变量如果是在函数中则存储在栈区。如果全局变量则存储在全局/静态存储区可能有人就要问了占用内存的什么区域有什么关系吗在此我简单提及一下。堆区new分配的内存在堆区使用new分配完之后需要使用delete进行进行内存释放如果不释放则会一直占用直到程序运行结束由操作系统释放。栈区函数的局部变量存放的地方函数运行结束时被释放。全局/静态存储区全局变量和静态变量存储的地方。程序运行结束后释放。delete使用new分配的内存都需要使用delete进行释放。需要注意1、一个new和一个delete对应。2、new完不delete会造成内存泄漏。3、new完多次delete是不允许的。4、不可delete声明变量获得的内存。new与动态数组这部分之后再写数组与指针首先我们来复习一下数组的定义一块连续的存储空间当中数组的名字就是数组第一个元素的地址。举例inta[10]{0,1,2,3,4,5,6,7,8,9};a就是a[0]的地址。即aa[0];这里我们对数组与地址做两个深入的思考。1、数组的指针表示方法由上可知数组第一个元素a[0]的地址是a即aa[0];也可以说对a进行解引用得到a[0]即a[0]*a;那数组第二个第三个…元素呢这里直接给出a[1]*(a1);a[2]*(a2);a[3]*(a3);...这就体现出来将指针变量加一后其增加的值等于指向类型占用的字节数。引用一下C Primer Plus的原话将指针包括数组名加1实际上是加上了一个与指指向的类型的长度以字节为单位相等的值。对于遍历数组而言使用指针加法和数组下标时等效的。同时这里引用C Primer Plus当中的一张图片便于大家更好的理解。需要注意的是使用sizeof函数对数组名使用得到的是数组的长度这里的数组名没有解释成地址。而对指针使用得到的是指针的长度。2、对数组名取地址由上面的论述可知数组名即为数组首元素的地址那如果我们进行以下操作呢inta[10]{0,1,2,3,4,5,6,7,8,9};coutaendl;coutaendl;//对数组名取地址会得到什么呢地址的地址吗实际上不是的在这里数组名也没有解释成为地址实际的输出为0x8f036e75a4850x8f036e75a485是的这两个输出是一样的但是含义却不一样。对于a也就是a[0]是一块4字节的内存对于a则是一块4x10字节的内存也就是说inta[10]{0,1,2,3,4,5,6,7,8,9};couta1endl;couta1endl;//对数组名取地址得到0x8f036e75a485 4 0x8f036e75a4890x8f036e75a485 4 x 10 0x8f036e75a4c5这就又体现出来属性的概念a的属性是int*a的属性是int(*)[20]