0%

C++中的指针

指针的基本概念

可以通过指针来保存一个地址

指针作用

可以通过指针间接访问内存

  • 内存编号是从0开始记录的,一般用十六进制数字表示
  • 可以利用指针的变量保存地址

指针的定义和使用

指针定义语法:数据类型 * 指针变量名例如int * p;

&为取址符,例如

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <iostream>
using namespace std;
int main()
{
int a=10;
int * p;
p=&a;
cout <<"a的地址为"<<&a<< endl;
cout<<"指针p为"<<p<<endl;
cout<<*p<<endl;
*p=1000;
cout<<a<<endl;
return 0;
}

使用指针可以通过解引用(解引用就是指针前加一个星号,例如*p)的方式来找到指针指向的内存所代表的数据

指针所占用的内存空间

指针保存的是一个地址(十六进制),在32位操作系统中占用4个字节,在64位操作系统中占用8个字节,这个可以在visual studio中修改

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <iostream>
using namespace std;
int main()
{
int a=10;
int * p=&a;
cout<<sizeof(p)<<endl;
cout<<sizeof(int *)<<endl;
cout<<sizeof(double *)<<endl;
cout<<sizeof(char *)<<endl;
return 0;
}

空指针和野指针

空指针

空指针:指针变量指向内存中编号为0的空间

用途:初始化指针变量

注意:空指针指向的内存是不可访问的(0~255的内存编号是系统占用的,因此不可访问)

1
2
3
4
5
6
7
8
9
10
#include <iostream>
using namespace std;
int main()
{
int * p=NULL;
cout<<*p<<endl;//访问报错,不允许访问

return 0;
}

野指针

野指针:指向一块非法的地址(随便指向了一块内存)

注意:在我们编程中,要避免出现野指针

1
2
3
4
5
6
7
8
9
10
#include <iostream>
using namespace std;
int main()
{
int * p=(int *)0x1100;
cout<<*p<<endl;//访问野指针,访问出错

return 0;
}

空指针和野指针都不是我们申请的空间,因此不要访问。

const修饰指针

const修饰指针有三种情况:

  1. const修饰指针——常量指针
  2. const修饰常量——指针常量
  3. const既修饰指针,又修饰常量

常量指针:指针指向可以修改,但是指针指向的值不可以修改

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <iostream>
using namespace std;
int main()
{
int a=10;int b;
const int *p=&a;
cout<<*p<<endl;//输出指针指向的值
cout<<p<<endl;
*p=20//错误,指针指向的值不可修改
p=&b;//正确,指针指向可以修改
cout<<p<<endl;
return 0;
}

指针常量:指针指向不可以修改,但是指针指向的值可以修改

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <iostream>
using namespace std;
int main()
{
int a=10;int b;
int * const p=&a;
cout<<*p<<endl;//输出指针指向的值
*p=20;//正确,指针指向的值可修改
cout<<*p<<endl;
p=&b;//错误,指针指向不可以修改
return 0;
}

const既修饰指针,又修饰常量:指针指向和指针指向的值都不可修改

指针和数组

作用:利用指针访问数组中的元素

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <iostream>
using namespace std;
int main()
{
int arr[]={1,2,3,4,5};
cout<<"第一个元素"<<arr[0]<<endl;
int *p=arr;//arr就是数组首地址
cout<<"利用指针访问第一个元素"<<*p<<endl;
cout<<p<<endl;
p++;//让指针向后偏移4个字节
cout<<"利用指针访问第二个元素"<<*p<<endl;
cout<<p<<endl;
p--;
cout<<"利用指针遍历数组"<<endl;
for(;*p<=5;p++)
{
cout<<*p<<endl;
}
return 0;
}

指针和函数

作用:利用指针作为函数参数,可以修改实参的值

值传递

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>
using namespace std;
void ex (int a,int b)//void为不限制数据类型
{
int t=a;
a=b;
b=t;
cout<<"形参a="<<a<<endl;
cout<<"形参b="<<b<<endl;
}
int main()
{
int a=10,b=20;
ex(a,b);
cout<<"实参a="<<a<<endl;
cout<<"实参b="<<b<<endl;
return 0;
}

地址传递(地址传递可以修饰实参)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>
using namespace std;
void ex (int *a,int *b)//void为不限制数据类型
{
int t=*a;
*a=*b;
*b=t;
cout<<"形参a="<<*a<<endl;
cout<<"形参b="<<*b<<endl;
}
int main()
{
int a=10,b=20;
ex(&a,&b);
cout<<"实参a="<<a<<endl;
cout<<"实参b="<<b<<endl;
return 0;
}

冒泡排序

经典利用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <iostream>
using namespace std;
int main()
{
int i,j,t,n;
int arr[]={4,3,6,9,1,2,10,8,7,11,12,14,13,5};
int len;
len=sizeof(arr)/sizeof(arr[0]);
for(i=0;i<len;i++)
{
for(j=0;j<i;j++)
{
if(arr[j]>arr[i])
{
t=arr[j];
arr[j]=arr[i];
arr[i]=t;
}
}
}
for(n=0;n<=len-1;n++)
{
cout<<arr[n]<<endl;;
}
return 0;
}

和指针联合利用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include <iostream>
using namespace std;
//冒泡排序函数 参数一:数组的首地址,参数二:数组的长度
void bubbleSort(int * arr,int len)
{
for(int i=0;i<len;i++)
{
for(int j=0;j<i;j++)
{
if(arr[i]<arr[j])
{
int t;
t=arr[i];
arr[i]=arr[j];
arr[j]=t;
}
}
}
}
//打印数组
void printArray(int *arr,int len)
{
for(int i=0;i<len;i++)
{
cout<<arr[i]<<endl;
}
}
int main()
{
//创建数组
int arr[]={4,3,6,9,1,2,10,8,7,11,12,14,13,5};
//数组的长度
int len=sizeof(arr)/sizeof(arr[0]);
//创建冒泡排序函数
bubbleSort(arr,len);
//打印排序后的数组
printArray(arr,len);
return 0;
}