目录
一.字符指针
二.指针数组
三.数组指针
四.函数指针
五.函数指针数组
六.指向函数指针数组的指针
一.字符指针
与整型指针类似,创建一个字符变量,取出地址,并存放到一个字符指针变量中,通过解引用操作可以修改字符值
//int main()
//{
// char ch = 'w';
// char*pc = &ch;
// *pc = 'a';
// printf("%c", ch);
//
//}
注意:char*p="abcdef";该代码并非是将整个字符串存入字符指针变量p中,而是将该字符串首元素的地址存放到变量p中。下面代码中的常量字符串是无法被修改的!
//int main()
//{
// const char*p = "abdef";//常量字符串
// //*p = 'w'; 无法修改
// //把字符串首元素a的地址存放到p变量中
// printf("%c", *p); //~ a
//}
关于常量字符串的实例:求如下代码的输出结果
int main()
{
char str1[] = "hello bit.";
char str2[] = "hello bit.";
const char *str3 = "hello bit.";
const 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 and str2 are not same\n" "str3 and str4 are same\n"
分析:str1,str2是分别初始化两个字符数组,开辟了两个空间,str1,str2皆是数组名:即为该数组首元素地址,当然是不同的;但是str3和str4指向的是一个同一个常量字符串。C/C++会把常量字符串存储到单独的一个内存区域,当 几个指针指向同一个字符串的时候,他们实际会指向同一块内存。
二.指针数组
整型数组:数组存放的元素是整型
字符数组:存放的是字符
指针数组:数组元素是指针:本质上是数组
指针数组的应用
int main()
{
int arr1[5] = { 1,2,3,4,5 };
int arr2[5] = { 2,3,4,5,6 };
int arr3[5] = { 3,4,5,6,7 };
int*parr[3] = { arr1,arr2,arr3 };
int i = 0;
for (i = 0; i < 3; i++)
{
int j = 0;
for (j = 0; j < 5; j++)
{
printf("%d ", *(parr[i] + j)); parr[i][j];
}
printf("\n");
}
return 0;
}
上述代码先是创建了三个数组,每个数组五个元素,每个元素为整数;又创建了一个指针数组,该数组有三个元素,存放上面三个整型数组的首元素地址;要想一次性打印出这三个数组可以遍历数组parr,parr[i]得到三个整型数组的首元素地址,比如parr[1]即可找到arr1,即为数组arr1首元素地址,加1可以得到这个数组下标为1的元素,加2可以得到这个数组下标为2的元素,以此类推.....
三.数组指针
整型指针:指向整型变量的指针
字符指针:指向字符变量的指针
数组指针:指向数组的指针
本质是:指针
判断下面哪个是数组指针
int *p1[10]; int( *p1)[10];
选int(*p2)[10]:p先和*结合,说明p是一个指针变量,然后指着指向的是一个大小为10个整型的数组。所以p是一个指针,指向一个数组,叫数组指针。 //这里要注意:[]的优先级要高于*号的,所以必须加上()来保证p先和*结合。
数组名 VS 取地址数组名:通俗一句话总结就是,数组名+1跨过的是一个数组元素,&数组名加1跨过整个数组,代码如下:
#include <stdio.h>
int main()
{
int arr[10] = { 0 };
printf("arr = %p\n", arr);
printf("&arr= %p\n", &arr);
printf("arr+1 = %p\n", arr+1);
printf("&arr+1= %p\n", &arr+1);
return 0;
}
结果如下:
数组指针的应用
当我们打印二维数组时,传参时,可以用二维数组接受;同时,数组名为数组首元素地址,而二维数组的首元素为一维数组,即一维数组的地址,对其解引用操作即可得到该一维数组,该数组+整数,即可得到该数组中各个元素的地址,再次解引用即可获得数组元素。代码如下:
void print(int(*p)[5],int r,int c)
{
int i = 0;
for (i = 0; i < r; i++)
{
int j = 0;
for (j = 0; j < c; j++)
{
printf("%d ", *((*p+i)+j));
}
printf("\n");
}
}
int main()
{
int arr[3][5] = { {1,2,3,4,5},{2,3,4,5,6},{3,4,5,6,7} };
//写一个函数打印二维数组
print(arr,3,5);
return 0;
}
四.函数指针
本质:指向函数的指针
#include <stdio.h>
void test()
{
printf("hehe\n");
}
int main()
{
printf("%p\n", test);
printf("%p\n", &test);
return 0;
}
注:此处&test等价于test. 函数名代表函数地址
void (*pfun1)();
pfun1可以存放。pfun1先和*结合,说明pfun1是指针,指针指向的是一个函数,指向的函数无参 数,返回值类型为void。
解析如下代码:
代码1 (*(void (*)())0)();
1、将0强转为函数指针类型,该指针指向一个参数为空,返回值为空的函数
2.对其解引用得到这个函数
3.调用该函数
代码2 void (*signal(int , void(*)(int)))(int);
1.signal是个函数,该函数的参数为int 以及一个指向函数的指针,该函数返回值为空,参数为int型,
2.去掉函数名和参数,即为返回值类型,因此该代码为一个函数的声明
为了更好的理解该代码,可以进行重命名操作
typedef void(* pf_t)(int)
则该代码为:pf_t signal(int,pf_t);
五.函数指针数组
定义:int (*parr1[10])();
应用:转移表(以模拟计算器为例) 代码如下
//模拟计算器
int Add(int x, int y)
{
return x + y;
}
int Sub(int x, int y)
{
return x - y;
}
int Mul(int x, int y)
{
return x*y;
}
int Div(int x, int y)
{
return x / y;
}
void menu()
{
printf("***********1.Add 2.Sub************\n");
printf("***********3.Mul 4.Div************\n");
printf("***************0.exit************\n");
}
void test()
{
int(*p[5])(int, int) = { NULL,Add,Sub,Mul,Div};
int input = 0;
int x = 0;
int y =0;
do
{
menu();
printf("请选择->:\n");
scanf_s("%d", &input);
if (input == 0)
{
break;
}
else if (input >= 1 && input <= 4)
{
printf("请输入操作数:\n");
scanf_s("%d %d", &x, &y);
int ret = p[input](x, y);
printf("%d\n", ret);
}
else
{
printf("请重新输入!");
}
} while (input);
}
int main()
{
test();
return 0;
}
六.指向函数指针数组的指针
定义:
函数指针pfun void (*pfun)(const char*);
函数指针的数组pfunArr void (*pfunArr[5])(const char* str);
指向函数指针数组pfunArr的指针ppfunArr void (*(*ppfunArr)[5])(const char*) = &pfunArr;