指针的基本概念,一维数组的指针。
什么是指针
指针也称作指针变量,大小为4个字节(或8个字节)的变量,其内容代表一个内存地址。
sizeof(T*) 4字节(64位计算机上可能是8字节)
T是任何变量类型
指针的定义
类型名 * 指针变量名
如 floatp,p是指针变量名,变量p的类型是*float *
注意:保存地址的是p不是*p
通过表达式 *p可以读写从地址p开始的sizeof(float)个字节,*p等价于存放在地址p处的一个float类型变量。
注:float可以被任何变量类型替代
指针用法
char ch1 = 'a'
char *p = &ch1
char ch2 = *p
p = &ch2
* p = 'd'
注意要使用&取地址运算符(&x的类型是T*),p是地址,*p是p所指的变量
不同类型指针的相互赋值
不同类型的指针,如果不经过强制类型转换,不能直接赋值
int *pn,char *pc,char c =0x65;//0x是十六进制
pn = (int *)&c;
int n = *pn;//n值不确定
*pn = 0x12345678//编译能过但运行可能出错
运行出错的原因
n值不确定
*pn是int类型,读取四个字节,而c只占开始的一个字节
编译能过但运行可能出错
从pn指向的4个字节往里面写东西,但不能确定c后面的3个字节是否能够访问(操作系统不让访问,导致程序崩溃),或者可以访问,但这3个空间可能是其他变量的空间(程序出错)
指针运算
两个同类型的指针变量可以比较大小
地址p1<地址p2 p1<p2的值为真
同类型的指针变量可以相减
两个T*类型的指针p1和p2
p1-p2=(地址p1-地址p2)/sizeof(T)
指针变量加减一个整数的结果是指针
n:整数类型的变量或常量
p+n:T*类型的指针,指向地址:
地址p+n * sizeof(T)
可自增,可自减
T*类型的指针p指向地址n
p++,++p:p指向n + sizeof(T)
指针可以用下标运算符[]运算
p[n]等价于*(p+n)
空指针
地址0不能访问,指向地址0的指针就是空指针
可以用”NULL”关键字对任何类型的指针进行赋值,NULL实际上就是整数0,值为NULL的指针就是空指针
指针可以作为条件表达式使用。如果指针的值为NULL,则相当于为假,值不为NULL,就相当于为真
指针和数组
数组是特殊类型的指针
指针形式的数组运算:
int *p;
int a[200];
p=a;//p指向数组a的起始地址,即p指向a[0]
*p=10;//a[0]=10
*(p+1)=20;//a[1]=20
p[0]=30;//a[0]=30
for(int i = 0;i<10;++i){
*(p+i)=i;//对数字的前10个元素进行赋值
}
p = a + 6//p指向a[6]
颠倒一个数组
void reverse(int *p,int size){
int i;
for(i=0;i<size/2;++i){
int tmp = p[i];
p[i]=p[size-1-i];
p[size-1-i]=tmp;
}
}
指针和二维数组
二维数组的地址是连续存放的,所以二维本质上是一维。
void reverse(int *p,int size){
int ihttps://github.com/hexojs/hexo/files/2246484/log.txt
for(i=0;i<size/2;++i){
int tmp = p[i];
p[i]=p[size-1-i];
p[size-1-i]=tmp;
}
}
int a[3][4]={{1,2,3,4},{5,6,7,8}};
reverse(a[0],5);
颠倒后的数组为
{{5,4,3,2},{1,6,7,8}}
指向指针的指针
T **p
p是指向指针的指针,p指向的地方存放着一个类型为T*的指针
*p的类型是T*
int **pp;//是指向int*类型指针的指针
int *p;
int n = 1234;
p = &n;//n的类型是int*
pp=&p;//*pp是p,所以*(*pp)是n
指针和字符串
char *p=”asadcd”
char name[20];
scanf("%s",name);
name是char *类型的,name实际上就是地址
void指针
因sizeof(void)没有定义,所以*p无定义,++p等运算也无定义
void指针的用处
在头文件cstring中声明的内存操作库函数memset用到了void指针
void *memset(void * dest,int ch,int n);
dest是void*,所以可以是任何类型的指针,ch是字符的ASCII码
将从dest开始的n个字节都设置成ch,返回值是dest,ch每次只对一个字节起作用。
char a[200]=""//空串每一个位置都是"\0"
memset(a,'a',10)//将前10个字符设置为’a‘
输出a数组得到aaaaaaaaaa
memset函数的用处
清空(运用sizeof),无穷大(0x3f),初始化最大值(0x7f),详解见memset函数详解
函数指针
基本概念
程序运行期间,每个函数都会占用一段连续的内存空间。函数名就是该函数所占内存区域的起始地址(也称入口地址)我们可以将函数的入口地址赋给一个指针变量,然后通过指针变量就可以调用这个函数。这种指向函数的指针变量称为“函数指针”。
定义形式
类型名 (*指针变量名)(参数类型1,参数类型二….)
类型名是函数的返回类型
例如:
int(*pf)(int,char);
表示pf是一个函数指针,他所指向的函数的返回值为int,该函数有两个参数
使用方法
先定义指针;
把函数名赋值给指针变量名;
指针变量名名(实参表);