定义指针
数据类型* 指针变量名
int* p是定义名为p的指针变量
注意*是和int在一起的
*和p在一起时代表解引用
取地址:&a是取变量a的地址
int a = 10;
int* p;
p = &a;//指针变量p用于记录变量a的地址
cout << "a的地址是:" << &a<<endl;
cout << "指针p为:" << p << endl;
使用指针
解引用找到指针指向的内存的内容
指针前加*代表解引用,找到指针指向的内存中的存储的数据
*p = 1000;//为 指针p所指向地址的内存代表的变量 赋值
cout << "a= " << a << endl;
cout << "*p= " << *p << endl;
指针所占的内存空间大小
x86是32位系统
x64是64位系统
在32位系统下指针所占字节为4,不管是什么数据类型
64位下所占字节为8
指针变量用来存放地址
空指针(指针初始化)
指向内存中编号为0的空间
用于:初始化指针变量(不知道某个指针该指向哪个地址,先初始化让他指0了)
空指针指向的地址不可访问 0~255之间的内存编号是系统占用的 不可访问
错误示例如下:
int* q = NULL;
cout << *q << endl;
将会引发
同样的
野指针
指向非法的内存空间
非自己定义的内存空间,乱指的话可能没有访问权限
int* q = (int*)0x1100;
cout << *q;
const对指针的修饰
常量指针
指向常量的指针
指针的指向可以修改,指针指向的内存的值不可以通过指针来修改
但是可以对指向的地址进行修改
比如
c=100;
int c = 10;
int d = 20;
const int* ptr = &c;
cout << "修改前: " << *ptr << " 此时指向的地址是:" << ptr << endl;
//错误用法:试图修改指针指向的常量值
//*ptr = 20;
//正确用法:
ptr = &d;
cout <<"修改后: "<< * ptr << " 此时指向的地址是:" << ptr << endl;
指针常量
这个指针变量本身是一个常量
指针的指向不可以修改,但是它所指的内存的值可以修改
int* const ptr2 = &c;
//错误用法:试图修改指针的方向
//ptr2=&d;
//正确用法:
cout << "修改前变量c的值是:" << c<<endl;
*ptr2 = 666;
cout << "修改后变量c的值是:" << c<<endl;
指针和指针所指向的值都是常量
const int* const ptr3 = &c;
//错误用法:
//*ptr3 = d;
//ptr3 = &d;
指针与数组
int array[10] = {
1,2,3,4,5,6,7,8,9,10 };
cout << "第一个元素为:" << array[0] << endl;
int* p = array;//array是数组的首地址
cout << "利用指针指向首地址输出第一个元素: " << *p << endl;
p++;//或写作p = p + 1; 此处不是偏移一个字节而是偏移四个字节,因为每个指针在32位系统中占据4个字节
cout << "利用指针指向首地址输出第2个元素: " << *p << endl;
//遍历一遍数组
p = array;//重新将指针指向数组首地址
for (int i = 0; i < 10; i++)
{
cout << *p<<endl;
p++;
}
指针与函数
区分函数的值传递和地址传递
值传递只能改变形参
函数还可以使用地址传递来改变主程序中的实参
地址传递可以通过地址 间接 改变实参值
void swap(int* p1, int* p2)
{
int temp = *p1;
*p1 = *p2;
*p2 = temp;
}
//主程序
int a=10,b=20;
cout << "地址swap前的a和b: "<< a <<" "<< b<<endl;
swap(&a, &b);
cout <<"地址swap后的a和b: "<< a << " " << b << endl;
修改后的示意图:
小知识:
当数组要传入函数时,除了传入首地址,常常还传入一个长度,这个len=sizeof(a) / sizeof(a[0]),方便函数的for循环使用