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