C++ 指针
一、变量的内存地址(变量放在哪里)
每一个变量都有一个内存位置,每一个内存位置都定义了可使用连字号(&)运算符访问的地址,它表示了在内存中的一个地址。请看下面的实例,它将输出定义的变量地址:
1 2 3 4 5 6 7 8 9 10 | #include<bits/stdc++.h> using namespace std; int main() { int a; a=19; cout<<a<<endl; //变量a的值 cout<<&a<<endl; //变量a的地址在内存的位置 return 0; } |
运行结果
19
0x22fedc //变量a的首地址
在计算机中,内存空间是按字节进行编址,即每8个位都有一个地址。不同类型的数据占用的内存大小不一样,如int占4字节,上例中a占用从0x22ffedc开始的4个字节。
内存地址是16进制的。
二、什么是指针?
指针是一个变量,其值为另一个变量的地址,即,内存位置的直接地址。就像其他变量或常量一样,您必须在使用指针存储其他变量地址之前,对其进行声明。指针变量声明的一般形式为:
type *var-name;
在这里,type 是指针的基类型,它必须是一个有效的 C++ 数据类型,var-name 是指针变量的名称。用来声明指针的星号 * 与乘法中使用的星号是相同的。但是,在这个语句中,星号是用来指定一个变量是指针。以下是有效的指针声明:
int *ip; /* 一个整型的指针 */
double *dp; /* 一个 double 型的指针 */
float *fp; /* 一个浮点型的指针 */
char *ch; /* 一个字符型的指针 */
所有指针的值的实际数据类型,不管是整型、浮点型、字符型,还是其他的数据类型,都是一样的,都是一个代表内存地址的长的十六进制数。不同数据类型的指针之间唯一的不同是,指针所指向的变量或常量的数据类型不同。
三、C++ 中使用指针
使用指针时会频繁进行以下几个操作:定义一个指针变量、把变量地址赋值给指针、访问指针变量中可用地址的值。这些是通过使用一元运算符 * 来返回位于操作数所指定地址的变量的值。下面的实例涉及到了这些操作:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | #include<bits/stdc++.h> using namespace std; int main() { int a; int * pa; a=19; cout<<a<<endl; //变量a的值 cout<<&a<<endl; //变量a的地址在内存的位置 pa=&a; //把变量a的地址给pa cout<<pa<<endl; cout<<*pa<<endl; return 0; } |
运行结果
19
0x22fed8
0x22fed8
19
注意pa本身也有内存地址
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | #include<bits/stdc++.h> using namespace std; int main() { int a; int * pa; a=19; cout<<a<<endl; //变量a的值 cout<<&a<<endl; //变量a的地址在内存的位置 pa=&a; //把变量a的地址给pa cout<<pa<<endl; cout<<*pa<<endl; cout<<&pa<<endl; //pa的内存地址 return 0; } |
19
0x22fedc
0x22fedc
19
0x22fed8//pa的内存地址
注意
不允许把一个数赋予指针变量
1 2 | int *point; point=200; |
或者
1 2 3 | int a=200; int *point; *point=a; |
以上这些写法都是错误的
四、结构体指针
指向结构体类型的指针
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | #include<bits/stdc++.h> using namespace std; struct node{ int x; int y; }; int main() { node *npa; npa= new node; //指针的初始化 cin>>npa->x>>npa->y; cout<<npa->x<< " " <<npa->y<<endl; return 0; } |
五、指针的初始化与运算
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | #include<bits/stdc++.h> using namespace std; int main() { int *pa,*p; cout<<pa<< " " <<p<<endl; //pa,p的值,注意它代表的是一个地址值,没有初始化为随机值 cout<<&pa<< " " <<&p<<endl; //pa,p存放在内存的位置,在变量定义系统给定,不会改变 pa= new int [10]; //初始化pa为指向10个int类型的指针pa存储第一个int类型的首地址 p=pa; cout<<pa<< " " <<p<<endl; //pa,p的值会改变 cout<<&pa<< " " <<&p<<endl; //这行可以证明pa,p的位置不变 for ( int i=1;i<=10;i++) { cout<<p<< " " ; p++; } cout<<endl; cout<<p<< " " <<pa<< " " <<p-pa<<endl; p=pa; for ( int i=1;i<=10;i++) { cout<<pa[i-1]<< " " <<p[i-1]<<endl; //没有初始化内存地址的内容是随机的 } for ( int i=1;i<=10;i++) { cout<<*(pa+i-1)<< " " <<*(p+i-1)<<endl; } } |
六、单链表
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | #include<iostream> using namespace std; struct node { int val; node *next; }; int main() { node *p=NULL,*v; int n; cin>>n; for ( int i=1;i<=n;i++) { v= new (node); cin>>v->val; v->next=p; p=v; } node *l; for (l=p;l;l=l->next) { cout<<l->val<< " " ; } } /* in 5 4 8 7 2 3 out 3 2 7 8 4 */ |
单链表的函数实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | /* 指针的引用 */ #include<iostream> using namespace std; struct node { int val; node *next; }; void add(node *&p, int x) { node *v; v= new (node); v->val=x; v->next=p; p=v; return ; } void list(node *l) { for (;l;l=l->next) { cout<<l->val<< " " ; } } int main() { node *p=NULL; int n; cin>>n; for ( int i=1;i<=n;i++) { int x; cin>>x; add(p,x); } /* node *l; for (l=p;l;l=l->next) { cout<<l->val<<" "; } */ list(p); cout<<endl; list(p); } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)