目录
指针
指针
指针,也叫地址,内存块的首地址,是一个常量。例如数组名就是一个常量。
指针变量
指针变量,存放指针(地址)数据的变量;
1,未经初始化的指针变量禁止使用;
2,把谁的地址赋给指针变量,就说,指针变量指向了谁;
3,在32/64位系统下,所有指针变量都是4/8个字节。
int main(){
int a=1000;
int *p=&a; //把变量a的地址赋值给指针变量p
printf("%d", sizeof(p)); //32位输出4,64位输出8;
return 0;
}
*p的含义
点找块,根据p代表的地址找内存块;
注意:若p为null,则*p会崩溃。
当*p为左值,是把值存入对应的内存块中,既就是*p解引用指针p来访问它所指向的内存块地址中存储的值;
当*p为右值,是把值从对应内存块中拿出。
int main(){
int a=1000;
int *p=&a; //把变量a的地址赋值给指针变量p
printf("%d\n", sizeof(p));//32位输出4,64位输出8
printf("%d\n",*p); //通过p所存的地址值,取出地址对应的内存块的值
*p=200; //*p的左值,给指针变量p内存块赋值200
printf("%d\n",*p);
int b=*p; //*p为右值,把*p的200赋值给变量b
printf("%d\n",b);
printf("%d\n",*p);
return 0;
}
p+n的含义
表示p代表的地址向右移动n个储存单元,得到一个新的地址;
在一个连续空间中,两指针相减,等于间隔的内存空间数。
int main(){
int a[5]={5,4,3,2,1};
int *p=a;
printf("p = %d\n",p); //输出2090859680
printf("p+1 =%d\n",p+1); //输出2090859684
printf("p+2 =%d\n",p+2); //输出2090859688
printf("*(p+2)=%d\n",*(p+2)); //输出3
printf("*p+2 =%d\n",*p+2); //输出7
}
p[n]的含义
p代表的地址后的第n+1个内存块(下标为n的内存块)
int main(){
int a[5]={5,4,3,2,1};
int *p=a;
printf("%d\n", sizeof(p[4]/p[0]));//输出4,但第一个下标为0,所以实际上是第5块
printf("p=%d\n",p[4]); //输出1
}
支持运算
①算术运算,两指针不能相加,可以相减;
②自增自减,
*p++,可理解为先找到p内存块,在指向p+1内存块;
(*p)++,可理解为块里的值自增;
③强转
④逻辑运算
⑤赋值运算
⑥条件运算(三目)
⑦逗号运算
⑧sizeof关键字
⑨& *
指针的拓展
名称(xx指针) | 含义 | 定义形式 | 指针p的类型 |
变量指针 | 指向变量的指针 | | |
常量指针 | 指向常量的指针 | | |
(一维)数组指针 | 指向一维数组的指针 | | |
(二维)数组指针 | 指向二维数组的指针 | | |
函数指针 | 指向函数的指针 | | |
指针数组 | 返回指针的数组 | | |
指针函数 | 返回指针的函数 | | |
数组指针
数组的指针变量,保存的就是数组的首地址。
int a[10] = { 9,8,7,6,5,4,3,2,1,0};
int *p = a;
cout <<" p:" << p << endl; //指针p存放数组a的首地址
cout << "*p:" << *p << endl;
cout << "*(p+1):" << *(p + 1) << endl;
//输出
// p=00F6FC74
//*p=9
//*(p+1)=8
指针数组
每个数组元素都是指针(地址)。
int a[10] = { 9,8,7,6,5,4,3,2,1,0};
int *arr[10];
for (int i=0;i<10;++i)
{
arr[i] = &a[i];
cout << " arr["<<i+1<<"]=" << arr[i] << endl;
cout << "*arr[" << i + 1 << "]=" << *arr[i] << endl;
}
//输出
// arr[0]=001EF7BC
//*arr[0]=9
//......
函数指针
函数指针变量,变量保存的是函数的地址(函数名)。
#include <stdio.h>
int add(int a, int b) {
return a + b;
}
int main() {
// 声明一个函数指针变量,该指针可以指向返回整型、参数为两个整型的函数
// 初始化函数指针变量,让它指向 add 函数
int (*p)(int, int)=add;
// 使用函数指针调用 add 函数,既回调函数
int sum= p(5, 5);
//或者直接调用函数add
//int sum =add(5,5);
printf("sum =%d\n", sum);
return 0;
}
指针函数
返回指针的函数。
#include <stdio.h>
#include <stdlib.h>
// 指针函数,返回两个整数的和的指针
int* add(int a, int b) {
//动态分配内存存储数值的和
int *sum =(int*)malloc(sizeof(int));
// 计算并存储整数值的和
*sum= a + b;
// 返回指向整数值的和的指针
return sum; // 返回指向整数值的和的指针
}
int main() {
int x = 5;
int y = 5;
// 调用指针函数,获得指向两个整数值的和的指针
int* sum= add(x, y);
printf("sum = %d\n", *sum);
return 0;
}
空指针
指针变量指向内存编号为0的空间(不指向任何有效对象或函数的指针)
初始化指针变量,但其指向内存不可访问
c++中常用nullptr(NULL / 0)表示。
int main() {
//指针变量p指向内存地址编号为0的空间
int * p = NULL;
//访问空指针报错
//内存编号0 ~255为系统占用内存,不允许用户访问
cout << *p << endl;
system("pause");
return 0;
}
野指针
指针变量指向非法的内存空间;
一般是在释放或超出了所其指向对象的作用域之后任保持原来的地址。在程序中使用野指针会导致未定义的行为,因为野指针指向的内存可能已经被重新分配给其他对象,或以及被释放,但指针本身仍保留该地址,因此,对野指针的解引用操作会导致程序崩溃或产生意外结果。
int main() {
//指针变量p指向内存地址编号为0x1100的空间
int * p = (int *)0x1100;
//访问野指针报错
cout << *p << endl;
system("pause");
return 0;
}