指针的作用:存储内存地址,我们可以通过指针间接访问内存
内存的编号是从0开始的,一般用十六进制数字表示,我们可以利用指针变量来保存内存的地址
指针变量的定义和使用
指针的定义
语法:
数据类型 * 指针变量名 ;
例1:
#include <iostream>
using namespace std;
int main() {
int a = 10;
int* p; // 定义指针变量p,该变量只能存内存地址
//p = a; // 报“不能将int类型的值,分配到“int *”类型的实体
p = &a; // &符号可以取出变量a的内存地址,然后赋值给指针变量p
system("pause");
return 0;
}
指针的使用
例1:
#include <iostream>
using namespace std;
int main() {
int a = 10;
int* p; // 定义指针变量p,该变量只能存内存地址
//p = a; // 报“不能将int类型的值,分配到“int *”类型的实体
p = &a; // &符号可以取出变量a的内存地址,然后赋值给指针变量p
system("pause");
return 0;
}
例2:
#include <iostream>
using namespace std;
int main() {
int a = 10;
// 指针的定义
int* p; // 定义指针变量p,该变量只能存内存地址
//p = a; // 报“不能将int类型的值,分配到“int *”类型的实体
p = &a; // &符号可以取出变量a的内存地址,然后赋值给指针变量p
// 指针的使用
cout << "指针变量p的值是:" << p << endl; // 打印指针变量p的值,即变量a的内存地址
cout << "变量a的内存地址是:" << &a << endl;
cout << "获取指针p指向的值:" << *p << endl; // *p进行解指针操作,获取指针变量直线地址的值
system("pause");
return 0;
}
指针所占的内存空间
指针存储的是内存地址,所占内存空间为:32位操作系统4个字节(不区分数据类型都一样),64位系统站8个字节(不区分数据类型都一样)
例1:
#include <iostream>
using namespace std;
int main() {
int a = 10;
// 指针的定义
int* p; // 定义指针变量p,该变量只能存内存地址
cout << "指针类型所占内存空间为:" << sizeof(int *) << endl; // 64位为8,32位为4
cout << "指针类型所占内存空间为:" << sizeof(p) << endl;
system("pause");
return 0;
}
空指针和野指针
空指针
空指针是指针变量指向的内存编号为0的空间,一般用于初始化指针变量,必须注意的是空指针指向的内存是不可访问的
例1:
#include <iostream>
using namespace std;
int main() {
int a = 10;
// 指针的定义
int* p = NULL;
//cout << *p << endl; // 获取空指针的值,报“空指针异常错误”
cout << p << endl; // 打印指针p的内存地址:结果全是0
system("pause");
return 0;
}
运行例1代码出现的空指针异常截图:
野指针
野指针是指针变量指向了非法的内存空间
例1:
#include <iostream>
using namespace std;
int main() {
int a = 10;
// 指针的定义
int* p = (int *)0x1100; // 该内存是随便写的,语法和编译都没问题
cout << *p << endl;
system("pause");
return 0;
}
例1运行结果报错截图:
const修饰指针
const修饰指针有三种情况:
- const修饰指针 常量指针
- const修饰常量 指针常量
- const既修饰指针,又修饰常量
const修饰指针
常量指针:指针变量的指向可以修改,但是指针变量指向的值不能修改==
语法:
const 数据类型 * 指针变量名; // 常量指针
例1:
#include <iostream>
using namespace std;
int main() {
int a = 10;
int b = 20;
const int * p = &a; // const定义常量指针
cout << p << endl;
//*p = 30; // 修改常量指针指向地址的值,报错“表达式必须是可修改的左值”
p = &b; // 修改常量指针指向的地址
cout << p << endl;
system("pause");
return 0;
}
const修饰常量
指针常量:指针变量的指向不能修改,但是指针变量指向的值可以修改
语法:
数据类型 * const 指针变量名 ; // 指针常量
例1:
#include <iostream>
using namespace std;
int main() {
int a = 10;
int b = 20;
int * const p = &a; // const定义指针常量
cout << *p << endl;
*p = 30;
//p = &b; // 修改指针常量指向地址的值,报错“表达式必须是可修改的左值”
cout << *p << endl;
system("pause");
return 0;
}
const既修饰了指针也修饰了常量
指针指向的和指针指向的值都不能更改
语法:
const 数据类型 * const 指针变量名 ;
例1:
#include <iostream>
using namespace std;
int main() {
int a = 10;
int b = 20;
const int * const p = &a; // const定义指针常量
cout << *p << endl;
// *p = 30; // 修改常量指针指向地址的值,报错“表达式必须是可修改的左值”
// p = &b; // 修改指针常量指向地址的值,报错“表达式必须是可修改的左值”
cout << *p << endl;
system("pause");
return 0;
}
指针和数组
利用指针访问数组中的元素。
例1:
#include <iostream>
using namespace std;
int main() {
int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
int* p = arr; // 将数组arr的地址赋值给指针变量p
cout << "正常使用for循环取出所有的值:" << endl;
for (int i = 0; i < (sizeof(arr) / sizeof(arr[0])); i++)
{
cout << arr[i] << endl;
}
cout << "利用指针取出所有的值:" << endl;
for (int i = 0; i < (sizeof(arr) / sizeof(arr[0])); i++) // sizeof(arr) / sizeof(arr[0])计算出数组长度
{
cout << *p << endl; // 打印值
p++; // 指针自增,每次增加四个字节
}
system("pause");
return 0;
}
指针和函数
利用指针做函数参数,可以修改实参的值
例1:
在前面我们创建过一个函数,交换两个变量的值,在函数内部形参进行了交换,而在函数外部的实参没有任何改变,利用指针作为形参,可以改变实参的值
#include <iostream>
using namespace std;
void swap01(int num1, int num2)
{
cout << "交换前:" << endl;
cout << "num1=" << num1 << endl;
cout << "num2=" << num2 << endl;
int temp = num1;
num1 = num2;
num2 = temp;
cout << "交换后:" << endl;
cout << "num1=" << num1 << endl;
cout << "num2=" << num2 << endl;
}
void swap02(int* num1, int* num2)
{
cout << "交换前:" << endl;
cout << "num1=" << *num1 << endl;
cout << "num2=" << *num2 << endl;
int temp = *num1; // 解指针,对值进行交换
*num1 = *num2;
*num2 = temp;
cout << "交换后:" << endl;
cout << "num1=" << *num1 << endl;
cout << "num2=" << *num2 << endl;
}
int main() {
int a = 100;
int b = 200;
cout << "调用前:" << endl;
cout << "a=" << a << endl;
cout << "b=" << b << endl;
cout << "值传递:" << endl;
swap01(a, b);
cout << "——————————华丽的分割线——————————" << endl;
cout << "指针地址传递:" << endl;
swap02(&a, &b);
cout << "调用后:" << endl;
cout << "a=" << a << endl;
cout << "b=" << b << endl;
system("pause");
return 0;
}
指针配合函数和数组综合案例
例1:
#include <iostream>
using namespace std;
void Bubblesort(int* arr, int len) // 定义冒泡排序函数
{
for (int i = 0; i < len - 1; i++) {
for (int j = 0; j < len - i - 1; j++) {
if (arr[j] > arr[j + 1])
{
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
}
void PrintArr(int* arr, int len) // 定义数组打印函数
{
for (int i = 0; i < len; i++)
{
cout << arr[i] << endl;
}
}
int main() {
// 定义数组
int arr[] = { 4,2,5,8,1,3,6,9,7 };
int len = sizeof(arr) / sizeof(arr[0]); // 获取数组的长度
cout << "冒泡排序前:" << endl;
PrintArr(arr, len); // 打印排序前的数组
Bubblesort(arr, len); // 进行冒泡排序
cout << "冒泡排序后:" << endl;
PrintArr(arr, len); // 打印排序前的数组
system("pause");
return 0;
}