近来实习无聊,复习一下c++的内容,指针作为c++一个很重要的特性,涉及内容有点点绕,我尽量用自己能明白的话表达,有错误还望指正。
本文参考地址:cplusplus.com官方教程
Introduction
在c++中,变量声明之后会被存在内存中,可以通过变量名(the identifier)进行访问,这种情况下程序不需要考虑变量的物理地址。
对于一个C++程序来说,计算机的内存就像一连串的内存单元,每个单元的大小为一个字节,每个单元都有一个唯一的地址。这些单字节的内存单元的排序方式是允许大于1个字节的数据表示占据具有连续地址的内存单元。
对于每一个内存单元都有唯一的地址,并且连续的内存单元地址也是连续的。e.g. 地址为1776的内存单元在1775之后。
变量声明之后,在程序运行时,操作系统会给变量分配地址并存到相应的位置。在程序中,指针的使用是为了得到变量的地址。
Address of operator &
变量的地址可以通过这种方式获得
1 | address = &a; //将变量a的地址赋值给address |
假设myvar的地址为1776:
1 | myvar = 25; |
注:foo和bar的物理地址是运行时随机分配的。
这里的foo变量就是指针。
Dereference operator *
储存物理地址的变量为指针。*这个操作符可以被读作”value pointed to by”.
接上面例子
1 | baz = *foo; //read as "baz equal to value pointed to by foo" |
baz为25。foo 的值为 1776,*foo为1776所指向的值。
总结:
1 | myvar == 25 |
指针的声明
在声明指针时,数据类型必须是这个指针指向变量的数据类型,即与指针本身值无关。例:
1 | int* number; |
这里可以将 int*
看作一个数据类型,即整数的指针。一个栗子
1 |
|
注意两个指针同时声明 !==int * p1, * p2;==
指针和数组
数组的概念与指针有关,数组被隐形的转换为该数据类型的指针,工作原理是指向第一个元素的指针。与指针不同的是,数组不可以被赋值(即不能变成其他的地址),而指针可以。
栗子!
1 |
|
p从数组第一元素依次后移,==5种不同的给数组元素的赋值方法==
在关于数组的一章中,括号brackets([])被解释为指定数组元素的索引。那么,事实上,这些括号是一个被称为偏移(offset)操作符的引申(dereferencing)操作符。它们和*一样,对后面的变量进行去引号,但是它们也会把括号之间的数字加到被引号的地址上。例如:
1 | a[5] = 0; |
这里的两种表达是一样的,不管a是数组还是指针都是相同的。如果a是数组,那么a这个名字就是指向第一个元素的指针。
数组的初始化 intialization
声明方式
1 | int myvar; |
在上面这个例子中 注意区分==myptr = &myvar
==和==*myptr = &myvar
== (运行第二个,会报错,不能将int* 转化为int。即*myptr
是int,&myvar
是地址。
指针计算
不同数据类型指针的计算
1 | char *mychar; |
==++,–和*之间的优先级关系==:
++和–运算符可以用作prefix /suffix。作为前缀,增量发生在表达式执行前,而作为后缀,增量发生在表达式执行后。这里涉及到一个优先级的关系 ++优先级>*
*p++
就等同于*(p++)
。而它所做的是增加p的值(所以它现在指向下一个元素),但由于++被用作后缀,所以整个表达式的值被评价为原来的指针所指向的值(被增量前它所指向的地址)。
四种不同的组合
1 | *p++ // same as *(p++): increment pointer, and dereference unincremented address |
另一个例子
1 | *p++ = *q++; |
因为++的优先级比* 高,所以p和q都是递增的,但因为这两个递增运算符(++)都是作为后缀,所以在p和q都递增之前,分配给 *p的值是 *q。然后两者都被递增。所以等同于
1 | *p = *q; |
所以!具体应用时,为了防止混淆加括号加括号加括号!
总结
本文总结了指针的定义和比较基础的用法,指针的更多内容还请翻阅我的博客文章,感谢阅读。