文章目录
- 7 指针
- 7.1 指针的基本概念
- 7.2 指针变量的定义和使用
- 7.3 指针所占内存空间
- 7.4 空指针
- 7.5 野指针
- 7.6 void*指针
- 7.7 指向指针的指针
- 7.8 const修饰指针
- 7.9 指针和数组
- 7.10 指针和函数
7 指针
指针是指向另外一种类型的符合类型,和引用类似,指针也实现了对其他对象的间接访问。注意,我们这里使用的是类似,说明之间还是有差异。
- 指针本身就是一个对象,允许对指针复制和拷贝,而且在指针存在的情况下,它可以前后指向不同的数据类型
- 指针无需在定义时就赋值,和其他内置类型一样,如果在初始化的时候没有复制,那么它也会拥有一个不确定的值
7.1 指针的基本概念
指针的作用:可以通过指针间接访问内存
- 内存编号是0开始记录的,一般用十六进制数字表示
- 可以利用指针变量保存地址
7.2 指针变量的定义和使用
指针变量定义语法:数据类型 *变量名;
指针定义范例:
int * a,*b;//说明a和b都是指向int数据类型的指针
*
的靠近有些人总不能理解
*
这个标志在定义中靠近哪边。其实靠近哪边都没错,如果你靠近变量名,说明你理解为该变量不是基本变量,而是一种指针类型,这样的话,如果你写成以下形式是可以的:int *p1,p2;
你也可以靠近int,但是这样的话每条语句中就只能定义一个变量,如下所示:
int* a; int* b;
我们在前面注意的两点提到过,指针需要指向不同的数据类型,那么,如果我想要取一个变量的地址该怎么取?我们要用到取地址符&
。
如果我们指向某变量后,想要取得地址对应的元素,那么我们可以使用解引用符*
来访问该对象。
让我们试着使用一下指针的定义,仔细体会其中的含义,代码如下所示:
#include <iostream>
using namespace std;int main()
{//1、定义指针int a = 10;//指针定义的语法:数据类型*指针变量名int* p = &a;cout << "a的地址为:" << &a << endl;cout << "指针p为:" << p << endl;//2、使用指针//可以通过解引用的方式来找到指针指向的内存//指针前面加*代表解引用,找到指针指向的内存中的数据*p = 1000;cout << "a = " << a << endl;cout << "*p = " << *p << endl;system("pause");return 0;
}
某些符号有多个含义
对于没有学过编程语言的来说,如果是首次接触C++,很容易被一堆符号搞晕。像
&
和*
这些符号,实际上有多个含义。下面我们用一些例子来看看它们在不同位置表示的不同含义。int i = 42; int &r = i; //&紧跟着类型名,因此是声明的一部分,而&r是一个引用,相当于42的别名,42的本名叫i,r和i都可以操纵42这个数据 int *p; //紧跟类型名出现,因此是声明的一部分,p是一个指针 p = &i; //&出现在表达式中,是一个&取地址符 *p = i; //*出现在表达式中,是一个解引用符 int &r2 = *p; //&是声明的一部分,*是一个解引用符
7.3 指针所占内存空间
指针也是数据类型,那么这种数据类型占用多少内存呢?通过下面的演示,我们可以知道指针占有多少内存。
示例:
#include <iostream>
using namespace std;int main()
{//指针所占内存空间int a = 10;int* p = &a;//在32位操作系统下,指针是占4个字节空间大小,不管是什么数据类型//在64位操作系统下,指针是占8个字节空间大小cout << "sizeof(int *) = " << sizeof(int*) << endl;system("pause");return 0;
}
7.4 空指针
空指针
不指向任何对象,你可以理解为它指向一块未知的区域,而实际上该指针变量指向内存中编号为0的空间。其通常用于初始化指针变量。需要注意的是,在没有指向任何实质性的东西时,你可以查看空指针的地址,但是空指针所指向的内存数据是不可以访问的。
让我们试着敲一下下面的例子:
#include <iostream>
using namespace std;int main()
{//空指针//1、控制怎用于给指针变量进行初始化int* p = NULL;//2、空指针是不可以进行访问的//0~255之间的内存编号是系统占用的,不可以进行访问//*p = 100;system("pause");return 0;
}
tip:
在C++11中,我们可以让字面值nullptr来初始化指针,当然,由于空指针指向的是内存中的0号位,故我们指向让指针指向字面值0也可以达到空指针的效果。
int *p1 = nullptr;
int * p2 = NULL;
in * p3 = 0;
NULL还是nullptr
在以后的C++程序书写中,我们应该避免使用NULL,而多使用nullptr。
7.5 野指针
野指针通常指的是指针变量指向非法的内存空间。一般来说,指针都需要初始化,如果你没有初始化,那么在访问指针的时候就会出现问题。
示例:
#include <iostream>
using namespace std;int main()
{//野指针int* p = (int*)0x1100;cout << *p << endl;system("pause");return 0;
}
tip:
【总结:空指针和野指针都不是我们申请的空间,因此不要访问。】
7.6 void*指针
void*指针也叫通用指针
或泛指针
。对于这类指针,其可以存放任意数据对象。但是注意的是,不要试图去访问它,因为你不知道void *指针指向的是什么数据类型。
#include <iostream>
using namespace std;int main()
{//void*指针int a = 11;void* p = &a;cout << *p << endl;system("pause");return 0;
}
out:
7.7 指向指针的指针
指针变量本质上也是对象,故指针变量也是个地址。
#include <iostream>
using namespace std;int main()
{//void*指针int a = 11;int* p = &a;cout << "a的地址:"<< &a << endl;cout << "p指向的地址" << p << endl;cout << "p的地址"<<&p << endl;system("pause");return 0;
}
out:
7.8 const修饰指针
当一个变量被const修饰符限定时,那么他会变成常量,其值不能改变。在指针这一块内容中,const修饰指针会出现三种情况:
- const修饰指针——常量指针
- const修饰常量——指针常量
- const既修饰指针又修饰常量
上面显有点绕,我来总结一下。
让我们来看第一种情况:常量指针。
const int *p = a;
实际上其等于:
const(int *p) = a;
实际上等于:
const a;
在这种情况下,指针中存有的内容只能是常量,也就是说,指针的性质被保留了,还是可以随便指,那是指的内容他必须保证是一个常量,不能随便修改。
让我们来看第二种情况:指针常量。
int const *p = a;
如果是指针常量这种情况,说明指针变量名被const修饰了,此时这个指针变量变成指针常量了,那么指针就不能随便改了,而内容可以随便改因为没有限制。
综上所述,那么const int * const p
就是即修饰指针又修饰常量,那么指针的指向不能该,指针指的内容也不能改了。
示例:
#include <iostream>
using namespace std;int main()
{//1、常量指针int a = 10;int b = 10;const int* p = &a;//指针指向的值不可以改,但是指向可以改//*p = 20;错误p = &b;//正确//2、const修饰常量int* const p2 = &a;*p2 = 100;//p2 = &b;错误,指针的指向不可以改//3、const修饰指针和常量const int* const p3 = &a;//p3 = &b;错误//*p3 = 100;错误system("pause");return 0;
}
顶层const
从上面的
常量指针
我们看出const是修饰的是指针变量指向的数据,而指针常量
const修饰的是指针变量本身。为此,我们用术语顶层const
表示指针本身是个常量,而用底层const
表示指针所指的对象是一个常量。从上面所学我们也可以得知,指针类型既可以是顶层const也可以是底层const。
7.9 指针和数组
作用:利用指针访问数组中元素
示例:
#include <iostream>
using namespace std;int main()
{//指针和数组//利用指针访问数组中的元素int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };cout << "第一个元素为:" << arr[0] << endl;int* p = arr;//arr就是数组的首地址cout << "利用指针访问第一个元素:" << *p << endl;p++;//让指针向后偏移4个字节cout << "利用指针访问第二个元素:" << *p << endl;system("pause");return 0;
}
7.10 指针和函数
作用:利用指针作为函数参数,可以修改实参的值
原理:
示例:
#include <iostream>
using namespace std;//值传递交换函数
void swap01(int a, int b)
{int temp = a;a = b;b = temp;cout << "swap01 a = " << a << endl;cout << "swap01 b = " << b << endl;
}void swappoint(int *p1, int *p2)
{int temp1 = *p1;*p1 = *p2;*p2 = temp1;cout << "swappoint *p1= " << *p1 << endl;cout << "swappoint *p2= " << *p2 << endl;
}int main()
{//指针和函数//1、值传递int a = 10;int b = 20;swap01(a, b);cout << "a = " << a << endl;cout << "b = " << b << endl;//分界线cout << "------------" << endl;//2、地址传递int* p1 = &a;int* p2 = &b;swappoint(&a, &b);cout << "a = " << a << endl;cout << "b = " << b << endl;system("pause");return 0;
}