目录
1.引言:
2.字符指针
3.指针数组
4.数组指针
5.arr 和 &arr的区别
6.数组指针的使用
7.数组和指针传参
8.函数指针
9.函数指针数组
10.指向函数指针数组的指针
1).我们都知道指针是个变量,是用来存放地址的,而地址也形象的指向一个空间,因此地址 也被形象的称作指针。
2).指针在32位平台大小是4个字节,64位是8个字节。
3).指针也有自己的类型,指针的类型决定了我们用指针访问地址的时候看待的视角,因此 指针的类型决定了指针向前或者向后走一步有多大(距离)。
其中char*类型的指针pc+1跳过一个字节,int*类型的指针pi+1跳过4个字节。
字符指针有两种使用的场景:
(1)指向字符
#include
int main()
{
char ch = 'w';
char *pc = &ch;//取出w的地址放到pc指针中
*pc = 'w';
return 0;
}
(2)指向字符串
#include
int main()
{
char* pstr = "hello bit.";//这里实际上是把字符串的首字符h的地址放到了指针pstr中
printf("%s\n", pstr);
return 0;
}
其中hello bit是常量字符串,放在内存中的常量区。因为常量字符串是连续存储的,所以指针通过找到h,就可以找到剩下的字符串。
下面我们来看一道笔试题:
#includ
int main()
{
char str1[] = "hello bit.";
char str2[] = "hello bit.";
char *str3 = "hello bit.";
char *str4 = "hello bit.";
if(str1 ==str2)
printf("str1 and str2 are same\n");
else
printf("str1 and str2 are not same\n");
if(str3 ==str4)
printf("str3 and str4 are same\n");
else
printf("str3 and str4 are not same\n");
return 0;
}
因为str1和str2是两段完全独立的空间,因此存储两个数组的地址是完全不一样的。
但str3和str4都是常量字符串,存储在常量区中,不能被修改。因此相同的指针指向两个字符串。
通过编译器,结果也确实如此。
顾名思义指针数组就是一个存放指针的数组。
比如:char *arr1[ ]是存放字符指针的数组
int *arr2[ ]是存放整型指针的数组
代码1
#include
int main()
{
int a = 1;
int b = 2;
int c = 3;
int d = 4;
int *arr2[] = { &a, &b, &c, &d };//arr2就是一个整形指针数组
int i = 0;
for (i = 0; i < 4; i++)
{
printf("%d ",*(arr2[i]));
}
return 0;
}
代码2
与指针数组不同,数组指针是一个指针,即指向数组的指针。
跟整形指针和字符指针类似,数组指针是存储数组的地址的指针。
如:int (*parr)[10]= & arr;取出的是数组的地址放到指针中去
*表示parr是指针变量
向外看指针指向了一个数组[10],数组中有10个元素,每个元素类型为int.
int *arr=4; 去掉arr即表示指针类型是int
int (*arr) [ 10 ] ={ 0 } 去掉arr表示指针类型是int(*)[10],此处必须加(),因为[]的优先级要高于*号的,所以必须加上()来保证p先和*结合。
#include
int main()
{
int arr[10] = { 0 };
printf("%p\n", arr);
printf("%p\n", &arr);
printf("arr+1 = %p\n", arr + 1);//arr表示数组首元素地址,+1表示跳过一个元素,即4个字节
printf("&arr+1= %p\n", &arr + 1);//&arr表示整个数组的地址,+1表示跳过整个数组的地址,即40个字节
return 0;
}
int arr[5[={1,2,3,4,5};
int (*p)[5]=&arr;将一个数组的地址放到数组指针里面,但这种用法很少。
我们来举一个数组指针在二维数组传参的用法
学了指针数组和数组指针我们来一起回顾并看看下面代码的意思:
int arr[5] 整型数组:一个类型为int类型的整型数组
int *parr1[10] 整形指针数组:parr1是个数组,有10个元素,每个元素都是int *类型,所以parr1是个存放指针的数组。
int (*parr2)[10] 数组指针:*说明parr2是个数组指针
向外看,parr2指向数组,数组有10个元素,每个元素都是int 类型
int (*parr3[10])[5]:数组指针的指针数组:parr3是个数组,数组中有10个元素,每个元素都是一个数组指针。该指针指向的数组有5个元素,每个元素都是int类型。
(1)一维数组传参
(2)二维数组的传参
(3)一级指针传参
同理二级指针传参时,可以传二级指针变量pn或者&pn,可以用二级指针int **p或者其他类型的二级指针来接收.
顾名思义函数指针就是保存函数地址的指针
话不多说,我们直接上代码
那么我们来看个例子:
//代码1
(*(void (*)())0)();
//代码2
void (*signal(int , void(*)(int)))(int);
代码1表示将0先强制类型转换为void(*)()的函数地址
再对其解引用,就是调用0地址处的函数,而且被调用的函数是无参数的,没有返回值的
代码2
signal是函数名,signal函数有两个参数,第一个是int,第二个是void(*)(int)的函数指针类型。
去掉signal(int , void(*)(int)),整体函数类型是void(*)(int)的函数指针类型
顾名思义就是存放函数指针的数组
前面我们说了函数的地址可以放到函数指针里面,那么我们为什么还要创建函数指针数组呢?这是因为在一个大型工程里面,我们不可能每遇到一个函数的地址,都来创建一个函数指针,因此需要创建函数指针数组来存放多数的函数的地址。
代码:
顾名思义,指向函数指针数组的指针就是一个指针,指针指向一个数组,数组的元素都是函数指针。
int arr1[10]={0};
int (*parr1)[10]= &arr1; parr1就是指向整型指针数组的指针
int arr2[10]={0};
int *(*parr2)[10]=&arr2; parr2就是指向整型指针数组的指针
好啦,指针就简单介绍到这,剩下的我会后面一一介绍。