前言
之前在学习C语言的时候,指针并没有学得很好。但指针应该是比较基础但很重要的东西了,还是有必要再巩固一下下的,趁着最近在看一点C++的基础知识,感觉还是有必要整理一下指针的用法。
文章目录
一、指针是什么?
指针相对于一个内存单元来说,指的是单元的地址,而该内存单元中存放的就是数据。相较于其他的变量,指针变量是用来存放指向对象的内存地址的,因此指针变量也被称作内存变量。通俗一点讲,指针其实就类似于一个记录着数据准确地址的导引,你可以通过它来访问到储存在该地址下的数据。
二、指针类型和用法
2.1基本语法
2.1.1定义一个普通指针
type *指针名
四种有效指针声明
int *p /*定义一个整型指针*/
double *p /*定义一个double型指针*/
float *p /*定义一个浮点型指针*/
char *p /*定义一个字符型指针*/
/*为了是你的代码更加规范,最好在初始化的时候让指针指向空*/
2.1.2指针递增
#include <iostream>
using namespace std;
int main ()
{
int var[3] = {1,2,3};
int *ptr;
// 指针指向数组
ptr = var;
for (int i = 0; i <3; i++)
{
cout << "Value of var[" << i << "] = ";
cout << *ptr << endl;
// 指针移动到下一个位置||指针递增
ptr++;
}
return 0;
}
2.2指针数组和数组指针区别
简单来说,指针数组是一个数组变量,这个数组变量里面储存的元素都是指针;数组指针是一个指针变量,这个指针变量指向的地址就是该数组的首个元素的地址。
指针数组的定义:
char *arr[2] = {"1","2"};
数组指针的定义:
char (*arr)[2];
//用例
char arr[2] = {'a','b'};
char (*arr)[2]=&arr;
2.3指向指针的指针
2.3.1概念
指向指针的指针其实就是二级指针,即第二级的指针变量存放的就是第一级指针的地址,第一级指针指向的索引变量的地址。这是一种多级间接寻址的形式,形成的就是一个指针链。
2.3.2定义一个指向int类型的指针
int **p;
我们将a的地址给p,再把p的地址给q,此时就可以通过二级指针来索引到我们想要的变量了
int a = 100;
int *p = &a;
int **q = *p;
printf("%d",**q);
2.4将指针传递给函数
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
void Add(int *p){
*p+=1;
};
int main() {
int num = 1;
cout<<num;
int *p ;
p = &num ;
cout<<num<<endl;
Add(p);
cout<<num<<endl;
}
2.5返回指针的函数
声明:
int *function(){...}
在该函数中,会将指针变量以一个函数返回值的形式return出来。
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
char *name(int id)//自定义函数
{
char *str_name[]={//初始化
"无效",
"yiliziba",
"dayu",
"xiaobai",
};
char *p;
if(id>=1 && id<=3) //判断是否合法
p=str_name[id];
else
p=str_name[0];
return p;
}
int main()
{
int i;
cout<<"输入角色序号:";
cin>>i; //输入月份
cout<<"人物名称:"<<name(i);
return 0;
}
从上面的代码片段我们可以看到,name函数返回的就是一个指针变量地址。我们可以通过函数返回指针来执行某些函数内的操作。
三、二级指针和多级指针
在文章前半部分我已经记录了指向指针的指针,其实这就是二级指针。那么三级指针就是指向(指向指针的指针)的指针,好奇怪的描述哈哈哈,也可以理解是套娃吧。多级指针有啥用呢?其实指针的用法往往最常见的就是在数组中的操作。
其实在C语言体系下,对于初学者来说,感觉不太方便的就是数组在初始化定义的需要先定义数组的长度,这种操作就比较难受了,有很多程序在设计编写的时候其实你没办法确定用户要输入多大的数据,这时候一个可变长度的数组就比较重要了。
嗯,先把大佬的代码整理下来吧。
这里给出大佬代码:
include <iostream>
#include <cstring>
using namespace std;
class CArray
{
int size; //数组元素的个数
int* ptr; //指向动态分配的数组
public:
CArray(int s = 0); //s代表数组元素的个数
CArray(CArray & a);
~CArray();
void push_back(int v); //用于在数组尾部添加一个元素 v
CArray & operator = (const CArray & a); //用于数组对象间的赋值
int length() const { return size; } //返回数组元素个数
int & operator[](int i)
{ //用以支持根据下标访问数组元素,如“a[i]=4;”和“n=a[i];”这样的语句
return ptr[i];
};
};
CArray::CArray(int s) : size(s)
{
if (s == 0)
ptr = NULL;
else
ptr = new int[s];
}
CArray::CArray(CArray & a)
{
if (!a.ptr) {
ptr = NULL;
size = 0;
return;
}
ptr = new int[a.size];
memcpy(ptr, a.ptr, sizeof(int) * a.size);
size = a.size;
}
CArray::~CArray()
{
if (ptr) delete[] ptr;
}
CArray & CArray::operator=(const CArray & a)
{ //赋值号的作用是使 = 左边对象中存放的数组的大小和内容都与右边的对象一样
if (ptr == a.ptr) //防止 a=a 这样的赋值导致出错
return *this;
if (a.ptr == NULL) { //如果a里面的数组是空的
if (ptr)
delete[] ptr;
ptr = NULL;
size = 0;
return *this;
}
if (size < a.size) { //如果原有空间够大,就不用分配新的空间
if (ptr)
delete[] ptr;
ptr = new int[a.size];
}
memcpy(ptr, a.ptr, sizeof(int)*a.size);
size = a.size;
return *this;
}
void CArray::push_back(int v)
{ //在数组尾部添加一个元素
if (ptr) {
int* tmpPtr = new int[size + 1]; //重新分配空间
memcpy(tmpPtr, ptr, sizeof(int) * size); //复制原数组内容
delete[] ptr;
ptr = tmpPtr;
}
else //数组本来是空的
ptr = new int[1];
ptr[size++] = v; //加入新的数组元素
}
int main()
{
CArray a; //开始的数组是空的
for (int i = 0; i<5; ++i)
a.push_back(i);
CArray a2, a3;
a2 = a;
for (int i = 0; i<a.length(); ++i)
cout << a2[i] << " ";
a2 = a3; //a2 是空的
for (int i = 0; i<a2.length(); ++i) //a2.length()返回 0
cout << a2[i] << " ";
cout << endl;
a[3] = 100;
CArray a4(a);
for (int i = 0; i<a4.length(); ++i)
cout << a4[i] << " ";
return 0;
}
程序的输出结果为:
0 1 2 3 4
0 1 2 100 4
总结
总算把指针再回顾了一遍,具体指针的应用还是比较灵活的。多级指针的使用在数据结构的学习和应用上也是比较重要的,所以学好指针是必备的基础呐,大家一起加油吧!!!
喜欢的小伙伴举个爪子点个赞~~~