今天研究一下指针的一些东西,方便之后使用。
我们用 \(\&\) 来获取变量的地址。当这个用于定义的时候表示引用。
int a=1; std::cout<<&a<<std::endl; int &b=a; printf("%d\n",b); b=2; printf("%d %d\n",a,b);
output:
0xfffefe04 1 2 2
其中第一个值是不一定的。
int a=1,*b; b=&a; printf("%d %d\n",b,*b); *b=2; printf("%d %d\n",a,*b);
output:
-66044 1 2 2 3 3
这样我们得到了一个指针 \(b\) 。我们使 \(b\) 指向 \(a\) 。可以发现,我们直接访问 \(b\) ,会得到它所存的地址。而要访问其值,则要使用 \(*\) 对其进行解引用。然后双方的权值动态更新,保持一直,这是因为他们都访问同一个地址,其存储的数据是相同的。
我们对于没有地址指向的指针一般赋予 \(NULL\) 以防止程序出错。所以我们可以用下面的代码检验指针是否为空。
int a=1; int *p1=NULL,*p2=&a; if(!p1) printf("p1为空\n"); if(!p2) printf("p2为空\n");
output:
p1为空 p2不空
指针还可以指向结构体。
struct node{ int x,p; }; node a={1,2}; node *p=&a; printf("%d %d\n%d %d\n",(*p).x,(*p).p,p->x,p->p);
output:
1 2 1 2
除了访问元素与正常的指针无差别,但是可以使用 \(->\) 直接访问内部元素。
我们支持这四种操作: ++ -- + -
当我们使用这个操作:
int a=1,*p=&a; printf("%x\n",p); ++p; printf("%x\n",p);
output:
fffefe04 fffefe08
发现其地址增加了 \(4\) ,这是因为 \(int\) 占据 \(4byte\) ,如果用 \(char\) ,那么将增加 \(1\)。但是应当注意,这种情况下我们直接++,可能会导致你不知道你访问的是什么地方。
所以我们这么用。
int a[10]={0,1,2,3,4,5,6,7,8,9}; int *p=a; int tim=10; while(tim--){ printf("%d ",*p); ++p; }
output:
0 1 2 3 4 5 6 7 8 9
注意不能开到第11组,容易寄。
这个和++是反的,不多说了。
这个和++差不多,但是不是自加,而是加出一个值。
是+的反操作,不多说了。
(这个部分写的好水啊)
然后+= -=
什么之类的是一样的,加几个就是几个当前类型的大小。
就是地址值的比较,其他和普通变量差不多。
这个刚才讲了,就不多说了。
int a[3]={10,11,12}; *a; //都可修改 ++a;//不行,因为它算是常量,赋值也同理 *(a+1); //这些加的操作也行
就是一堆指针,和普通数组除了存的东西不一样没啥区别。
我们可以用 \(new\) 来为指针分配空间,使得它可以在空间中游走。
但是用完需要 \(delete\) 释放空间,然后删掉之后还要赋值为 \(NULL\)防止 RE
。
int *a=new int[10]; delete[] a;a=NULL;
多维数组就自己计算一下就可以一维表示了,不多说了。
但是一般不这么搞,容易寄。我们一般把指针对到已经开好的数组上、
指向指针的指针!
这你指向的什么就往什么前面加一个 \(*\) 就好了,一般用的不多。
我们把地址往函数里指针那么位置传就行了,其实类似引用,但是这个可以用于传数组。
当然函数也可以返回指针,实际上是被处理过的地址被扔了回来。
一般指针有什么用?可以卡空间,可以快速交换两个数组,还可以快速传递数组。
具体应用到算法中,有:基数排序在线卡空间。数据结构动态开空间。长链剖分当场传空间。
指针还可以方便的维护跳表等,总之就是有蛮多妙用的还是。