指针
指针
指针运算符
【优先级】
- 后置++,--
- 前置++,-- 逻辑!* &
- 算数运算符
- 关系运算符
- && ||
- 赋值运算符
【注意】
*&a=*(&a) (自右向左)
&*a=&(*a) (自右向左)
【注意】
*(p++) 加的是地址,然后取出地址的值
(*p)++ 加的是从地址中取出的值
指向数组的指针(这里只举二维的例子)
int a[x][y];
a+i; |
a的第i行首地址 |
|
*(a+i) |
a[i]=&a[i][0] |
a的第i行首地址 |
*a+i |
&a[0][i] |
a的第0行第i个元素地址 |
*(*(a+i)+j) |
a[i][j] |
a的第i行第j列的元素 |
限定指针
指向常量的指针(*在后面)
const int* p;
int const* p;
指针常量(*在前面)
int* const p;
常量指针常量
const int * const p;
【区别】
前提:p里面存放着&a,即a的地址
指向常量的指针:a不可以修改,p存放的地址可以修改(如p=&a; p=&b)
指针常量:a的值可以修改,p存放的地址不可修改(如*p=6; *p=7;)
【意义】
使指针及指针间接访问的内容受到强制保护,预防意外的变动,提高程序的健壮性。
指针数组
【语法】类型 *数组名[长度];
【举例】char *p[4];
【注意】char (*p)[4];(这是指向数组的指针,即:定义一个指针变量,它指向有4个元素的一维数组。)
//如果有一个数组a[5][3],指针p指向a
(*p)[3] ([]里面要填列数)
i行j列元素怎么表示: *(*(p+i)+j)
*p[5] ([]里面要填行数)
i行j列元素怎么表示: *(p[i]+j)
【用法】
1. 初始化
char *a[]={"abc","jht","abcd"};
char *p=name;(name为字符型二维数组)
2. 数组顺序交换
char *temp=p[i];
p[i]=p[j];
p[j]=temp;
返回指针值的函数
【注意】确保返回地址的意义(返回全局变量的地址,而非局部变量的地址)
指向函数的指针
【函数指针】函数的入口地址
【指向函数的指针】指向函数指针的指针变量
【用法】
//(设有个函数int name(int a,int b))
int prc(int x,int y,int (*name)(int,int))
{
return (*p)(x,y);
}
【意义】那为什么不直接name(x,y),而要这样写?
这种方法常用来实现菜单驱动系统,程序提示用户从菜单中选择一个选项,每个选项都有一个不同的函数来完成其功能。
*p[]和(*p)[]
说明:
(*p)[n]:根据优先级,先看括号内,则p是一个指针,这个指针指向一个一维数组,数组长度为n,这是"数组的指针",即数组指针;
*p[n]:根据优先级,先看[],则p是一个数组,再结合*,这个数组的元素是指针类型,共n个元素,这是"指针的数组",即指针数组。
定义:
如果有一个数组a[5][3]
指针p指向a
(*p)[3] //(这种方法[]里面要填列数)
* pp[5] //(这种方法[]里面要填行数)
初始化:
(*p)[3]=a;
for (i = 0; i < n; i++)
{
pp[i] = a[i];
}
储存空间:
数组指针是一个指针变量,占有内存中一个指针的存储空间;
指针数组是多个指针变量,以数组的形式存储在内存中,占有多个指针的存储空间。
取值:
//两种方法
*(*(p+i)+j);
*(p[i]+j);