时间长了容易和其他的记混。特记录一下:
1.指针变量基本概念
1.1、变量三要素:
(1)数据类型 [按对象性质不同分为不同的子集]
(2)变量名 [方便写代码,左值时赋值 右值时取值]
(3)存放变量的内存地址 [变量本身占用系统内存的位置,变量本身需要分配内存,指针变量也一样,都是分配后不变的]
1.2、基本数据类型:
(1)C语言中有四种:char(字符型)、int(整数型)、float(单精度浮点数)、double(双精度浮点数);用于整型的限定词有short、long、signed、unsigned。
(2)C++中多了bool,wchat_t
1.3、指针类型声明和定义:
(1)声明[不分配内存] 存储类型 数据类型* 指针变量名;
(2)定义[分配内存] 指针变量名=变量地址;
(3)声明+定义 存储类型 数据类型* 指针变量名=变量地址;
int numA; //声明不分配内存
numA = 10; //定义分配内存
int numB = 20; //声明定义分配内存
int *pA; //声明不分配内存
pA = &numA; //定义分配内存
int *pB = &numB; //声明定义分配内存
2.指针运算符
2.1、&运算符
&运算符:返回这个操作数的地址。如p=&a; 返回变量a的地址
int numB = 20;
int *pB = &numB;
2.2、*运算符
*运算符:返回这个操作数中存储的地址值所指向的(指针是什么类型就返回什么值)值;如b=*p;返回指针p所指向的值
int numB = 20;
int *pB = &numB;
*pB = 30; // numB=30;
2.3、->运算符
语法糖;为了方便,从"(*)." 运算符演化为"->"
3.指针移动/指针基本运算
3.1、+/-
指针可以加减一个整数,若p为指针,n为整数,则可以p+n/p-n;理解为:p+n*sizeof(数据类型TYPE)/p-n*sizeof(数据类型TYPE)
指针不可以两个指针相加,这样没有意义,可以相减,这样能知道距离大小或者算出占用多少个字节等(要注意算的是指针类型的个数)
3.2、=
有两种情况【p1,p2都为指针】
(1)p1=p2 :将p2赋值给p1
(2)*p1=*p2 :将p2指向的值赋给p1指针指向的值
3.3、< <= > >= == !=
允许两指针进行比较
3.4、++,--
自增自减,相当于3.1中的p+1/p-1 (要区别后增减和前增减)
4.指针地址的有效性
要保证指针永远指向一个有效地址,否则很容易出BUG
5.指针变量初始化
. 指针变量初始化时保证是有效地址或者NULL(c)或者nullptr(C++)
6.const限定指针变量
6.1、指向常量的指针[常量指针]
const int *p //声明指向常量的指针
表示:指针可以改变,但不可以通过指针改变指针指向的值(*p=是错误的)
const int numA = 10; // 常量
const int numB = 20; // 常量
const int *pB = &numB;
*pB = 200; //错误,不能给常量赋值
pB = &numA; //正确,可以给指针赋值
*pB = 100; //错误,不能给常量赋值
6.2、指向常量的指针 指向 非常量
int numA = 10;
const int *pA = &numA;
numA = 100; //那么此时pB指针指向的值也改变了
6.3、指针常量
int *const p
表示:指针本身不可以改变,但指针指向的值可以改变(*p= 重新赋值是正确的)
int numA = 10; // 常量
int *const pA = &numA; // 指针常量必须定义时就初始化
int numB = 20;
pA = &numB; // 错误,pA是常量不能再次被赋值
6.4、指向常量的指针常量
const int *const p
表示:指针本身不可以改变,指针所指向的值也不可以改变
即初始化后就不能改变指针指向和指针所指向的值 (p= / *p= 都是错误的,都不能为左值)
int numA = 10;
const int *const pA = &numA; // 指针常量必须定义时就初始化
*pA = 100; // 错误
int numB = 20;
pA = &numB; // 错误
7.void指针变量
在一般情况下,指针的值只能赋给相同类型的指针。void类型不能声明变量,但是可以声明指针,万能指针类型即void指针可以指向任何类型的变量。
8.指针和数组
8.1、基础
在C/C++中指针和数组有剪不清里不乱的关系。
数组名是这个数组的起始地址,即第一元素的地址;
数组名是指针常量,即这个指针变量[数组名所代表的内存位置]是无法改变的,但指向的值是可以改变的
int arr[5] ; arr == &arr[0]; [arr 在某些时候可以看成是 int *const arr(指针常量)]
注意: arr与&arr区别
arr是int[5]类型 arr+1 == &arr[1]
&arr是int[5]*类型 &arr+1 == &arr[5](虽然数组,没有arr[5]元素,但却可以引用这个元素的地址&arr[5])
如下面实例将引出七种形式进行分析
int arr[5] = { 1,2,3,4,5 };
// 数组首地址
// 数组首元素的地址
printf("arr = %p\n", arr); // arr 类型int[5]
// 同一种类型
// &arr 整个数组的首地址
printf("&arr = %p\n", &arr); // &arr 类型int[5]*
printf("&arr + 1 = %p\n", &arr + 1);//&arr+1 类型int[5]*
// 同一种类型
printf("arr + 1 = %p\n", arr + 1); //arr+1 类型int*
printf("&arr[0] + 1 = %p\n", &arr[0] + 1);//&arr[0] + 1 类型int*
printf("========\n");
// 取值后+1
printf("*arr + 1 = %d\n", *arr + 1);
printf("arr[0] + 1 = %d\n", arr[0] + 1);
8.2、指针数组和数组指针
8.2.1、指针数组
char *arr[]={"h1","h2","h3"} ;即是数组内存储类型都是指针类型,即数组每个元素存储的是地址
8.2.2、数组指针
char (*arrptr)[3] ;即是arrptr是一个指针,指针类型是char[3]*,指向一个数组,类型为char [3]
int arr[5] = { 1,2,3,4,5 };
int (*arrptr)[5];
arrptr = &arr;
9.指针和函数的关系
9.1、指针函数
int* fun() 即是函数的返回值为指针变量
9.2、函数指针
int (*funptr)() 即是funptr是一个指针,指向一个函数的地址,类型为 int (*)()
#include <iostream>
using namespace std;
int ff()
{
cout << "ff" << endl;
return 0;
}
int main()
{
int(*funptr)(); // 声明一个函数指针
funptr = ff; // 进行赋值
// 调用函数
funptr();
(*funptr)();
}