用处、如何定义?
创建数据结构、动态分配内存、拦截软件进程等。
定义方法:type *var-name; 值得注意的是,在定义时*的位置可以贴在type处,效果是一样的,为了方便理解,我们下面将所有的定义都贴在type处
例如:
int* a; //等价于int *a;
char* c = NULL;
double* dd = # //此处的num为事先声明好的double类型变量
struct node* newNode; //结构体类型的指针
& 取地址符号
作用:用来得到某个数据所存放的地址。
示例:
#include <iostream>
using namespace std;
int main()
{
int a = 0;
char c;
cout << &a << endl << &c << endl;
return 0;
}
* 解引用符号
作用:解析地址对应的数据
示例:
#include <iostream>
using namespace std;
int main()
{
int a = 0;
int* p = &a; //注意,此处的*为声明int类型指针变量的符号,不是解引用符号
*p = 1; //此处的*也为解引用
cout << *p << endl; //此处的*为解引用符号
return 0;
}
重要的概念
- 在此,可以不严谨地认为指针=地址
- 指针变量是用来存放指针的变量,不能存放其他数据类型。比如用&对某个变量取值之后得到它的地址,才可以进行存放。
- 要注意的是,比如指针也是有类型的,比如int类型的指针变量只能存储int数据类型的地址,而不能存储char类型的地址,因为不同的数据类型所占的内存大小是不一样的。
- 解引用*可以认为是指针指向的地址的位置向后面几个位连起来读值
空指针NULL
要是我没记错的话,在iostream这个头文件里面有定义#define NULL 0
因此有一个简单的用法,可以用来检测指针是否为空
if (ptr){}
//此处的ptr为一个指针,可以通过指针是否为空来执行if语句
指针的运算 ++ — + –
- 指针++表示向下移动一个内存位置,比如一个int为4字节,一个int类型的指针的值++一次就自增32(一字节是8位),指向的内存位置往后挪动32位。同理,一个char类型的指针++一次就往后挪8位
- –和++为相反操作,不多赘述
+和-即为向前挪动或向后挪动若干个单位,例如:
#include <iostream>
using namespace std;
int main()
{
int var[3] = {1,2,3};
int* ptr = var;
ptr + 2;
cout << *ptr << endl;
return 0;
}
#include <>iostream>
using namespace std;
int main()
{
int* ptr = NULL; //声明指针的时候给它赋空值是个好习惯
int var[3] = {100,200,300};
ptr = var; //数组名就是一个地址,指向数组的首地址,是一个常量
cout << *ptr << endl;
cout << ptr << endl;
ptr++;
cout << *ptr << endl;
cout << ptr << endl;
ptr++;
cout << *ptr << endl;
cout << ptr << endl;
ptr++;
cout << *ptr << endl;
cout << ptr << endl;
ptr--;
cout << *ptr << endl;
cout << ptr << endl;
endl;
}
指针的比较
众所周知,地址是16进制的值,既然是值就可以进行比较
符号:> < ==
示例程序(遍历数组):
#include <iostream>
using namespace std;
#define max 4
int main()
{
int var[max] = {1,2,3,4};
int* ptr = var;
while(ptr <= &var[max - 1]) //数组的取值范围为0~3,此处应-1
{
cout << *ptr << endl;
ptr++;
}
return 0;
}
指针访问数组
如前所述,数组名为数组的首地址,故可以通过指针对数组进行操作
需要注意的是,数组名是一个地址常量,不可进行++、–运算,但是可以进行+、-运算
示例代码:
#include <iostream>
using namespace std;
int main()
{
int var[4];
int* ptr = var;
*ptr = 1;
*(ptr + 1) = 2;
*(ptr + 2) = 3;
*(ptr + 3) = 4; // *(ptr + 3) = 4; //用指针对数组进行赋值
while(ptr <= (ptr + 3))
{
cout << *ptr << endl;
ptr++;
} //用指针遍历数组
return 0;
}
需要注意的是,数组名是一个地址常量,不可进行++、–运算,但是可以进行+、-运算
#include <iostream>
using namespace std;
const int MAX = 3;
int main ()
{
int var[MAX] = {10, 100, 200};
for (int i = 0; i < MAX; i++)
{
*var = i; // 这是正确的语法
var++; // 这是不正确的
双重指针
简单地说,双重指针甚至多重指针就是对指针的操作进行套娃
示例代码:
#include <iostream>
using namespace std;
int main ()
{
int var;
int *ptr;
int **pptr;
var = 3000;
// 获取 var 的地址
ptr = &var;
// 使用运算符 & 获取 ptr 的地址
pptr = &ptr;
// 使用 pptr 获取值
cout << "var 值为 :" << var << endl;
cout << "*ptr 值为:" << *ptr << endl;
cout << "**pptr 值为:" << **pptr << endl;
return 0;
}
运行结果:
var 值为 :3000
*ptr 值为:3000
**pptr 值为:3000
传递指针给函数
我们都知道,给一个函数传递普通数据类型的形参时,系统会在内存中开辟一段临时的空间,用来存放拷贝过来的数据,在函数内运算之后进行销毁,这就意味着实参(即被拷贝的源数据)并不会发生改变
使用指针来进行函数操作,在函数内部操作的数据即为指针指向的数据,即会修改函数之外的数据
示例代码:
#include <iostream>
#include <ctime>
usng namespace std;
void getsecond(unsigned long* s)
{
*s = time(NULL); //使用解引用对指针指向的值进行修改
return;
}
int main()
{
unsigned long sec;
getSeconds(&sec); //传参,将sec的地址传入
while(1)
cout << "当前的秒数:" << sec << endl;
return 0;
}
传递数组指针给函数:
示例代码:
#include <iostream>
using namespace std;
double get_avg(int* arr,int size)
{
int temp = size;
int sum = 0;
while(size > 0)
sum += *(arr + size);
return sum / temp;
}
int main()
{
int[5] = {1,2,3,4,5};
cout << get_avg(&test,5);
return 0;
}
函数返回指针
C++不支持返回函数内局部变量的地址到函数外,除非定义为static或者new到堆区
示例代码:
#include <iostream>
#include <ctime>
#include <cstdlib>
using namespace std;
int* GetRandom()
{
static r[10];
srand((unsigned)time(NULL)); //设置时间为种子
for(int i = 0;i < 10;i++) //此处的i++和++i对程序是否有影响?
r[i] = rand();
return r;
}
int main()
{
int* p = NULL;
p = GetRandom();
for(int i = 0;i < 10;i++)
cout << "*(p + " << i << "):" << *(p + i) << endl;
return 0;
}