引言
#include <iostream>
#include <swap.h>
using namespace std;
// 1.
int main()
{
int a = 10;
int *b; //定义指针变量
b = &a; // &a 等于取a的地址
*b = 3; // 可以通过修改指针的值,来改变a中的值
a = 12; // 也可以直接修改a 的值
// 也可以 int *b = &a;
cout << a << endl; //获取a的值
cout << &a << endl; //获取a的地址
cout << b << endl; //指针保存a的地址
cout << *b << endl; //对指针取* , 取指针保存地址的值。
cout << &b << endl; // 对指针取&,取指针的地址
return 0;
}
7.3 指针所占内存空间
提问:指针也是种数据类型,那么指针占用多少内存空间?
#include <iostream>
#include <swap.h>
using namespace std;
// 1.
int main()
{
int a = 10;
int *b; //定义指针变量
b = &a;
// 32系统下,指针占用4个字节,64位系统,占8个字节
// 一般情况下,开发环境都是32操作系统
cout << sizeof(b) << endl; // 8 查看指针所占用的内存大小
cout << sizeof(*b) << endl; // 4 这里获取到的是a的值,所有是4字节
cout << sizeof(&b) << endl; //8
return 0;
}
7.4 空指针和野指针
空指针:指针变量指向内存中编号为0的空间。
用途:初始化指针变量。
注意:空指针指向的内存是不可以访问的。
示例:空指针
#include <iostream>
#include <swap.h>
using namespace std;
// 1.
int main()
{
// 空指针
// 1.空指针用于给指针变量用来初始化
int * pinter = NULL;
// 2.空指针是不可以访问的
// 0~255之间的内存编号是系统占用的,不可以访问
*pinter = 100; // 运行代码报错
return 0;
}
示例:野指针
野指针:指针变量指向的是非法的内存空间
#include <iostream>
#include <swap.h>
using namespace std;
// 1.
int main()
{
// 野指针
int *p = (int *)0x1100; //不可以指向不存在的内存
cout << *p << endl; //直接崩溃
return 0;
}
总结:空指针和野指针都不是我们主动申请的空间,因此不要访问
7.5 const修饰指针
常量指针
#include <iostream>
#include <swap.h>
using namespace std;
// 1.
int main()
{
// const修饰指针 - 常量指针
// 特点:指针的指向可以修改,但是指针指向的值不可以修改
int a = 10;
int b = 20;
const int *p = &a; //常量指针
p = &b; //正确,指针的指向可以修改
// *p = 21; //错误,指针指向的值不可以修改
cout << *p << endl;
}
指针常量
#include <iostream>
#include <swap.h>
using namespace std;
// 1.
int main()
{
// const修饰指针 - 指针常量
int a = 10;
int b = 20;
int * const p = &a; // 指针常量
// 特点:指针的指向不可以改,指针指向的值可以修改
*p = 12; // 可以改
p = &a; //不可以改
cout << a << endl;
cout << *p << endl;
}
修饰指针,又修饰常量
#include <iostream>
#include <swap.h>
using namespace std;
// 1.
int main()
{
// const既修饰指针,又修饰常量
int a = 10;
int b = 20;
const int * const p = &a; //
// 特点:指针的指向不可以改,指针指向的值,不可改
// *p = 21; //错误
// p = &b; //错误
cout << a << endl;
cout << *p << endl;
}
技巧:看const后面紧跟着是指针还是常量,是指针就是常量指针,是常量就是指针常量
7.6 指针和数组
作用:利用指针访问数组中的元素
#include <iostream>
#include <swap.h>
using namespace std;
// 1.
int main()
{
//指针和数组
// 利用指针来访问数组中的元素
int arr[] = {1,2,3,4,5};
int *p = arr; // 数组名就是数组的首地址
cout << "查看指针没有偏移时达到地址" << p << endl;
cout << "数组第一个元素"<<*p << endl; //利用解引用,*p获取数组的值
cout << arr[0] << endl; //访问第一个元素
// 访问第二个元素
p++; //让指针让后偏移4个字节
cout << "查看指针偏移时达到地址" << p << endl;
cout << "数组第二个元素" << *p << endl;
cout << "==================" << endl;
cout << "利用指针遍历整个数组" << endl;
//利用指针遍历整个数组
int * p2 = arr;
for(int i=0;i<5;i++)
{
cout << * p2 << endl;
p2++;
}
cout << "方式二" << endl;
for (int *p2=arr;p2<&arr[5];p2++)
{
cout << * p2 << endl;
}
}
7.7 指针和函数
作用:利用指针做函数的参数,可以修改实参的值
#include <iostream>
using namespace std;
void swap(int a,int b)
{
int temp = a;
a = b;
b = temp;
cout << "函数里的值a,b = " << a << ","<< b << endl;
}
void swap2(int *a,int *b)
{
int temp = *a;
*a = *b;
*b = temp;
cout << "函数里的值a,b = " << *a << ","<< *b << endl;
}
int main()
{
//指针和函数
int a = 10;
int b = 20;
// 1. 值传递
// swap(a,b);
// cout << "值传递函数外的值a,b = " << a << ","<< b << endl; // 值传递不可以修改函数外的值,需要地址传递
// 2. 地址传递
int *p = &a;
int *p2 = &b;
swap2(p,p2); //函数传地址,函数需要指针去接收
cout << "值传递函数外的值a,b = " << a << ","<< b << endl; // 值传递不可以修改函数外的值,需要地址传递
}
总结:如果不想修改实参,就用值传递,想修改实参就地址传递
7.8 指针,数组,函数
案例描述:封装一个函数,利用冒泡排序,实现对数组的升序排序
例如数组:int arr[] = {5,2,4,3,1};
#include <iostream>
using namespace std;
void s(int * p,int len)
{
cout << p << endl;
//冒泡排序
for(int i=0;i<len-1;i++)
{
for(int j=0;j<len-i-1;j++)
{
if(p[j]>p[j+1]){
int temp = p[j];
p[j] = p[j+1];
p[j+1] = temp;
}
}
}
}
int main()
{
//案例描述:封装一个函数,利用冒泡排序,实现对数组的升序排序
int arr[] = {5,2,4,3,1};
int len = sizeof(arr)/sizeof(arr[0]);
s(arr,len); //传入数组和长度
cout << "排序后的数组" << endl;
for(int i = 0;i<5;i++)
{
cout << arr[i] << endl;
}
return 0;
}
7.9 指针偏移使用
#include <climits>
#include <iostream>
using namespace std;
int main(void)
{
int* arr = new int[5];
arr[0] = 0;
arr[1] = 1;
arr[2] = 2;
arr[3] = 3;
cout << "arr[1] is " << arr[1] << endl;
arr = arr + 1;
cout << "arr[1] is " << arr[1] << endl;
arr = arr - 1;
cout << "arr[1] is " << arr[0] << endl;
delete[] arr;
return 0;
}
指针地址概念
#include <climits>
#include <iostream>
using namespace std;
int main(void)
{
int arr[5] = { 1, 2, 3, 4, 5 };
cout << arr << endl;
cout << &arr << endl;
cout << sizeof(arr) << endl;
cout << sizeof(arr[0]) << endl;
cout << sizeof(&arr) << endl;
cout << sizeof(&arr[0]) << endl;
int* as = new int[5];
as[0] = 1;
as[1] = 2;
cout << sizeof(as) << endl;
cout << sizeof(&as) << endl;
delete[] as;
return 0;
}
7.10数组指针
#include <stdlib.h>
#include <stdio.h>
/*
数组指针 [存储类型] 数据类型 (*指针名)【下标】 = 值
int 指针 p [3] 数组地址
指向一个数组的指针
数组指针相当于二级指针
*/
int main()
{
int a[3] ={10,20,30};
int b[2][3] = {1,2,3,4,5,6};
int (*p)[3] = &a;
p = b;
printf("a = %p \n",a);
printf("&a[0] = %p \n",&a[0] );
printf("&a = %p \n",&a);
printf("b = %p \n",b);
printf("&b = %p \n",&b);
printf("p = %p \n",p);
printf("&p = %p \n",&p); //二级指针的地址;
printf("a = %d \n",*a );
printf("p = %d \n",**p );
printf("p = %d \n",*(*p+1) );
exit(0);
}
7.11指针函数
本质是一个函数,返回值为指针
例子:返回值* 函数名(形参)如;int* func(int )
7.12函数指针
本质是指针,指向一个函数
类型 (*指针名)(形参表) void(*p)(int)
7.1.3指向指针函数的函数指针
int* (*p)(int)
7.13函数指针数组
本质是数组,
类型 (*数组名【下标】)(形参)如:int (*buf [ N ])(int)
int (*buf[2])(int,int);
buf[0] = add;
buf[1] = sub;
7.14指向指针函数的函数指针数组
int *(*funcp【N】) (int)