c++ 浅谈指针
指针
绝大部分参考自C++指针
概念
指针是“指向(point to)”另外一种类型的复合类型。
复合类型是指基于其它类型定义的类型。
指针的值实质是内存单元(即字节)的编号
有时你申请一个变量(如int x;
),计算机就会随机给你分配一个空间,你可以在那个空间内改变数值
就像计算机给了一个叫做a的小房子,但是只能在里面放int类型的值
比如你输入x=-1
,计算机首先会把小房子找到,然后把-1放在里面
(如果里面有其他值,就拿出来)
那这个小房子的地方在哪里呢,就存放在地址里
每一个变量都有一个地址(即是它在内存中的位置)
所谓指针就是一个箭头→,指向一个地址,然后这个地址里有一个值
声明
在类型后加上星号(*
)即可,当然指针也分类型的,即:
int* a;//一个指向int类型房子的指针a(当前还是随机值)
char* b;//一个指向char类型房子的指针b
如果你不知道类型,也可以用void* c;
int* a,b;
有些人要问了,如果写成上面那种形式的话,那a,b各是什么类型呢?
答案是a是int类型指针,b是int类型的普通变量。
所以通常申请指针这样写:
int *a,*b;
注意定义指针后指针会指向一个随机的位置
如果你对这个位置进行不正确的操作,就有可能发生内存错误
操作
赋值
首先我们要学习一个取地址运算符&
,它可以获取变量的地址
有些小伙伴或许并不陌生了,因为我们平常输入的时候都会用到它:
scanf("%d",&x);
这个句子的意思就是找到所在的地址,然后把输出的值放在里面
甚至可以输出一个地址,用和格式控制符,或者也可以用输出,这两种是可以等价替换的
如:
int a;
printf("%p\n",&a);
cout<<&a<<endl;
运行结果:
00000000007bfe1c0x7bfe1c
00000000007bfe1c0x7bfe1c
输出
*a
表示a指向的值。
#include<bits/stdc++.h>
using namespace std;
int main(){
int b;
int *a=&b;
*a=0;
printf("执行 *a=0 后,\n");
printf("指针的地址: %p\n",&a);
printf("指针指向的值: %d\n\n",*a);
*a=1000;
printf("执行 *a=1000 后,\n");
printf("指针的地址: %p\n",&a);
printf("指针指向的值: %d\n\n",*a);
//&a=1000的写法是错误的
return 0;
}
运行结果:
执行 *a=0 后,
指针的地址: 000000000067fe10
指针指向的值: 0
执行 *a=1000 后,
指针的地址: 000000000067fe10
指针指向的值: 1000
可以发现指针的地址并没有改变000000000067fe10
因为我们改变的是指针指向的地址所存的值
所以用*a
其实表示的是
加减操作
指针可不可以进行加减操作呢,我试了一下,答案是可以的
其实想起来很简单,把地址前移或后退一段地址,是可以的
#include<bits/stdc++.h>
using namespace std;
int main(){
int a=0,*b;
b=&a;
printf("指针指向的地址: %p\n\n",b);
b=b+1;
printf("指针指向的地址: %p\n\n",b);
printf("a的值: %d\n",a);
return 0;
}
运行结果:
指针指向的地址: 00000000007bfe14
指针指向的地址: 00000000007bfe18
a的值: 0
因为b指向的是一个int类型,这里就是相当于把b的地址后移一个int类型,就是
所以我们结果看到的是00000000007bfe18
,而不是00000000007bfe15
而指针指向地址的变化是不会改变原地址所存值的
所以a的值还是
同理:
#include<bits/stdc++.h>
using namespace std;
int main(){
bool a,*b;
b=&a;
printf("指针指向的地址: %p\n\n",b);
b++;
printf("指针指向的地址: %p\n\n",b);
return 0;
}
运行结果:
指针指向的地址: 000000000067fe17
指针指向的地址: 000000000067fe18
类型大小为,于是地址加
数组
以前我们操作通常都是酱紫:
#include<bits/stdc++.h>
using namespace std;
int n,a[102];
int main(){
printf("输入:\n");
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
printf("-------------------------\n");
printf("输出:\n");
for(int i=1;i<=n;i++)
printf("%d ",a[i]);
return 0;
}
学了指针,可以酱紫:
#include<bits/stdc++.h>
using namespace std;
int n,a[100];
int main(){
printf("输入:\n");
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",a+i);
printf("-------------------------\n");
printf("输出:\n");
for(int i=1;i<=n;i++)
printf("%d ",*(a+i));
return 0;
}
运行结果:
输入:
2
1 2
-------------------------
输出:
1 2
指针应用
指针与数组
我们知道,当定义数组int a[10];
时,系统会连续开10个空间,所以:
#include<bits/stdc++.h>
using namespace std;
int main(){
int a[10]={1,2,3,4,5,6,7,8,9,10};
int *p;
for(p=&a[0];p<&a[0]+10;p++)
printf("%d ",*p);
return 0;
}
当运行到第一次for循环是,p指针指向a[0]
的地址00000000007bfdf01
,其指向的值就是1
重点:&a[0]+10
是什么意思?
就是a[0]
的地址后移10位的地址,所以p小于&a[0]+10
本质上就相当于最初的输出的方法
其中a[0]
也可以换做a
也就是数组的首地址
#include<bits/stdc++.h>
using namespace std;
int main(){
int a[10]={100,200,300,400,500,600,700,800,900,1000};
printf("%d\n",*a);
printf("%d\n",*a+5);
printf("%d\n",*(a+5));//这条语句与上条有区别
return 0;
}
运行结果:
100
105
600
其中*a+5
和*(a+5)
的意义不同
*a+5
的意思是指向的值加,所以得到的是*(a+5)
的意思是的地址加,也就是&a[5]
,指向的值是
指针与函数
有时指针可以看成一个数组
如:
#include<bits/stdc++.h>
using namespace std;
int n;
int sum(int *A){
int _sum=0;
for(int i=1;i<=n;i++)
_sum+=A[i];
return _sum;
}
int main(){
int A[100];
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&A[i]);
printf("%d",sum(A));
return 0;
}
运行结果:
3
1 2 3
6
函数指针
函数指针甚至还可以指向函数,但指针的参数要和原函数一样。
注意:函数指针必须加上括号,否则系统会以为你定义了一个int类型的指针
于是:
#include<bits/stdc++.h>
using namespace std;
int n;
int (*p)(int*);//这里是函数指针
//int *p(int*);//不能这样写
int sum(int *A){
int _sum=0;
for(int i=1;i<=n;i++)
_sum+=A[i];
return _sum;
}
int main(){
int A[100];
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&A[i]);
p=sum;
printf("%d",p(A));
//也可以这样写:
//printf("%d",(*p)(A));
return 0;
}
运行结果:
3
1 2 3
6
不难发现:
p=sum;
printf("%d",p(A));
这一段是等于:
printf("%d",sum(A));
所以,这里的指针是指向的一个函数看上去好像没啥用
结构体指针
声明结构体指针就直接在名称前加*
即可,指向结构体成员有两种方法,以程序为例
#include<bits/stdc++.h>
using namespace std;
struct node{
int a,b;
}x,*y;
int main(){
y=&x;//y存的是x的地址
x.a=123;
x.b=987;
printf("%d\n",(*y).a);//第一种写法,一定要加括号
printf("%d\n",y->b);//第二种写法,不要加*号
return 0;
}
运行结果:
123
987
双重指针
双重指针指向的是某个指针的地址
如下:
#include<bits/stdc++.h>
using namespace std;
int main(){
int a=100,*b,**c;
b=&a;c=&b;
printf("%p %p %p %p\n",&a,b,*c,&c);
printf("%d %d %d\n",a,*b,**c);
return 0;
}
运行结果:
000000000067fe1c 000000000067fe1c 000000000067fe1c 000000000067fe08
100 100 100
完结撒花❀
★,°:.☆( ̄▽ ̄)/$:.°★ 。
本文作者:Yvette的博客
本文链接:https://www.cnblogs.com/yvette1217/p/16218701.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步