一.指针的概念
-
指针是一种数据类型,被称为"指针类型"。指针类型描述的是一个地址,这个地址指向内存中另外一个对象的位置。简单的说,指针表示的是它所指向对象的地址。这些地址包括变量,数组或函数。
-
C++编译系统在编译时会为不同数据类型的对象分配大小不同的存储空间。每个储存空间都有一个固定的编号。根据这个地址即可准确找到并访问这些储存单元。
-
定义整数型变量:
int a=5;
----------->如何取到整数变量a的地址? -
定义整数型指针变量:
int* pInt=&a;
-
定义如下指针:
char* p="hello";
数组内存分配结构如图所示,此时指针变 量p存储数组的首地址。
指针和指针变量的区别
A、指针是一种新的数据类型,这种数据类型专门用来存储内存地址。
B、XXX型指针是一种具体指针数据类型,用于描述相应数据类型的内存地址。
C、指针变量是一个变量,用于存放对应数据类型的地址值,只占用4个字节的 大小。
相关运算符(&,*)理解
#include <iostream>
using namespace std;
void main()
{
int a=5,*p=&a;//*表示类型说明
cout<<*p<<endl;//*p表示所指向的变量a的值
system("pause");
}
二 指针的定义和赋值
指针的定义
- 使用指针变量前必须先声明。
- 使用指针数据类型定义的变量,称为指针变量。用符号*表示此变量是指针变 量。
- 指针变量只能用来存放内存地址。
- 指针变量内存所占的大小是 4个字节。
- 指针变量的定义如下三种形式(常用第一种形式)
int* ptr1 = 0; //定义int型指针变量ptr1
char* ptr2 = 0; //定义char型指针变量ptr2
int *ip1,ip2; //声明了1个指针变量ip1和1个普通变量ip2
int *ip3,*ip4; //声明了两个整数型指针变量ip3,ip4
-
一次定义多个指针变量,每个指针变量前必须加“”,否则,只有前面 加“”的才能被解释成指针。
指针的赋值 -
任何一个指针变量,可以被赋值为空,即指针变量的值赋为
0
或NULL
或nullptr
; 指针变量的赋值运算有6种形式
(1)指针变量初始化赋值。如int* ptr1 = 0;
。
(2)把一个变量的地址赋值给相同数据类型的指针变量(地址运算符&—>& 变量)。
int *pa;
int a;
pa = &a; //把整型变量a的地址赋予整型指针变量pa
(3)把一个指针变量的值赋值给相同数据类型的另一个指针变量。
int *pa;
int a;
pa = &a;
int* pb = pa;//把pa的地址赋予指针变量pb
cout << pa <<"\n"<< pb;
(4)把数组的首地址赋值给指向数组的指针变量。
int a[5];
int* pa = a; //数组名表示数组的首地址,指针变量pa指向数组首地址 pa=&a[0];
(5)把字符串的首地址赋值给指向字符类型的指针变量。
const char *pc;
pc = "c language";//把字符串的首地址赋予指针变量 char *pc="c language";
(6)把函数的入口地址赋值给指向函数的指针变量。
int (*pf)();
pf=f; //f为函数名
//示例,方便测试理解
#include <iostream>
using namespace std;
int f(int a)
{
return a;
};
int main()
{
int(*pf)(int);
pf = f; //f为函数名
f(12);
system("pause");
}
举例说明
- 在代码栏输入以下代码,编译查看输出结果,注意查看两个内存地址是否一样:
#include <iostream>
using namespace std;
void main()
{ int a = 10;
int *p = &a;
cout<<&a<<endl;
cout<<p<<endl;
}
给指针变量赋值时需要注意:
(1)未经赋值的指针变量不能使用。
(2)指针变量的赋值只能赋予地址, 不能赋予任何其它数据。
三 指针的运算
未经赋值的指针变量不能使用。
指针只能进行赋值运算、间接引用运算、算术运算、两个指针的相减运算和两个 指针的比较运算
(1)赋值运算
取地址运算符& 和间接引用运算符解引用操作符 *
指针变量在使用之前必须有确定的指向。
NULL是一个指针常量,表示空地址。当指针变量暂时无法确定其指向或暂时不 用时,可以将它指向空地址,以保证程序的正常运行。
int a=0;
int* ptr1 = &a;
(2)间接引用运算
符号*也称为间接引用运算符,其运算结果为该指针所指对象的值。
int a=16,b=28;
int *pa=&a,*pb; //符号*表示pa、pb是指针变量
a*=b; //符号*表示进行乘法运算
*pa=123; //符号*表示间接引用pa所指向的对象a
(3)算术运算
- 与整数的加减运算和自增、自减运算。指针变量存储的是数据的内存地址, 因此可以将指针视为类似整型的变量。指针加上或减去一个整数,其结果是一个 新的地址值。
- 指针加上或减去一个整数n,表示指针从当前位置向后或向前移动n*sizeof< 数据类型>大小的地址空间。
int a=16;
int* pa=&a;
int *p1,*p2;
p1=pa+3;
p2=pa-2;
//变量a分配的首地址是0066FDF4,则p1=&a+3*sizeof(int)= 0066FDF4+3*4=0066FE00。同理p2=&a-2*sizeof(int)=0066FDF4- 2*4=0066FDEC。
如下图所示:
- 指针的自增或自减表示指针从当前位置向后或向前移动sizeof(数据类型) 大小的地址空间。
(4)两指针相减 - 当两个指针指向同一数组时,两个指针的相减才有意义。两个指针相减的结 果是一个整数,表示两个指针之间数组元素的个数。
int a[10];
int* p1=&a[1]; //p1指向a[1]
int* p2=&a[6]; //p2指向a[6]
int b=p2-p1; // b=5
(5)两个指针的比较运算
- 当两个指针指向同一个数组时,两个指针比较大小才有意义。 两指针变量可以进行关系运算。
#include <iostream>
using namespace std;
//pf1 == pf2 表示pf1和pf2指向同一数组元素;
//pf1 > pf2 表示pf1处于高地址位置;
//pf1 < pf2 表示pf1处于低地址位置。
#include <iostream>
using namespace std;
void main() {
int a[10];
int* p1 = &a[1]; //p1指向a[1]
int* p2=&a[6]; //p2指向a[6]
if (p1 == p2)
{
cout<<"=="<<endl;
}
else
{
cout << "!=" << endl;
}
system("pause");
}
- 指针变量还可以与0比较,判断指针是否为空指针。
- p==0:表明p是空指针,表示它不指向任何变量;
- p!=0:表示p不是空指针。
- 指针变量为0和指针变量未赋值是不同的概念。
- 直接与0进行比较,判断是否为空指针,常用来内存是否分配成功以及 函数 入参检测。