目录
一、基本概念
作用:可以通过指针间接性访问内存。每一个变量都有一个属于自己的十六进制地址编号,使用指针可以通过地址操控这个变量。最典型的就是形参和实参。
- 内存编号从0开始记录,一般用十六进制数字表示。
- 可以利用指针变量保存地址。
二、指针的定义和使用
指针变量语法:
- 数据类型 * 变量名;
- * 指针变量:解引用,使用指针指向的数据。
示例:
#include<iostream>
using namespace std;
int main() {
//定义一个指针变量 数据类型 * 指针变量名;
int a = 1;
int* p;
//让指针记录变量a的地址,&为取地址符号
p = &a;
//打印地址
cout << "a的地址为:" << &a << endl;
cout << "指针p为:" << p << endl;
//指针p代表的值,指针变量前加 * 代表解引用,指向指针指向的数据
cout << "指针指向的位置数据为*p:" << *p << endl;
system("pause");
return 0;
}
三、空指针
定义:指针变量指向内存为0的空间。
用处:初始化指针变量。
注意:空指针指向的内存是不可以访问的,访问空指针系统会报错。
#include<iostream>
using namespace std;
int main() {
//定义一个空指针,指针指向一个编号为0的空间
int* p = NULL;
//内存编号0~255为系统占用内存,禁止用户访问
cout << *p << endl;//报错
system("pause");
return 0;
}
四、野指针
概念:指针变量指向非法的内存空间
#include<iostream>
using namespace std;
int main() {
//指针变量指向内存地址编号为0x1100的空间
int* p = (int*)0x1100;
cout << *p << endl;//报错
system("pause");
return 0;
}
避免野指针的方法:
1. 指针初始化
2. 小心指针越界
3. 指针指向空间释放即使置NULL
4. 避免返回局部变量的地址
5. 指针使用之前检查有效性
五、const修饰指针(常量指针?指针常量?)
const修饰指针时会出现常见的三种不同的情况。因为语法上相对类似,所以容易记混,但他们被const修饰的对象是不一样的。
- const修饰指针:常量指针;
- const修饰常量:指针常量;
- const既修饰指针又修饰常量。
一一对以上情况进行举例:
#include<iostream>
using namespace std;
int main() {
int a = 10;
int b = 10;
//const修饰指针:常量指针;指针的指向可以修改,但指向的值不能修改
const int* p1 = &a;
p1 = &b; //正确
*p2 = 100; //报错
//const修饰常量:指针常量;指针指向的值可以修改,但指向不能修改
int* const p2 = &a;
p2 = &b;//报错
*p2 = 100;//正确
//const既修饰指针又修饰常量;两者都不可修改
const int * const p3 = &a;
p3 = &b;//报错
*p3 = 100;//报错
system("pause");
return 0;
}
记忆方式:观察*是在const前(修饰常量),还是在const后(修饰指针)
六、指针和数组
作用:利用指针访问数组中的元素。因为数组中的元素在内存的排列是连续的。
可以通过以下案例来学习利用指针控制数组中相关元素的语法:
#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;//数组名就是数组的首地址
cout << "使用数组访问第一个元素:" << *p << endl;
p++;//使数组向后偏移4个字节(需根据元素数据类型所占内存空间决定)
cout << "使用数组访问第二个元素:" << *p << endl;
//使用指针遍历数组
int* p2 = arr;
for (int i = 0; i < 10; i++) {
cout << *p2 << endl;
p2++;
}
system("pause");
return 0;
}
七、指针和函数
作用:利用指针作为函数参数可以修改实参的值。
初次学习函数时我们平常所认识的是函数的值传递,就是把实际参数的值传入函数的形式参数中,但原本实际参数的值不会变化。利用指针我们可以学会将形式参数的地址传入函数中,从而在函数中改变实际参数的值。
#include<iostream>
using namespace std;
//值传递的函数
void swap1(int a, int b) {
int temp = a;
a = b;
b = temp;
}
//地址传递的函数
void swap2(int* p1, int* p2) {
int temp = *p1;
*p1 = *p2;
*p2 = temp;
}
int main() {
int a = 10;
int b = 20;
swap1(a, b);//值传递不会改变实参
cout << "a=" << a << endl;
cout << "b=" << b << endl;
swap2(&a, &b);//地址传递可以改变实参
cout << "a=" << a << endl;
cout << "b=" << b << endl;
system("pause");
return 0;
结果显示,a,b的值在形参确实发生了值的交换。