目录
一:函数指针
函数名就是函数的起始地址
函数指针的定义,示例如下:
#include<stdio.h>
int sum(int a,int b)//加
{
return a+b;
}
int muti(int a,int b)//乘
{
return a*b;
}
int substract(int a,int b)//减
{
return a-b;
}
void demoFunPoint()
{
//以上几个函数的返回相同 参数一致 数量类型
//定义一个函数指针:复制函数首部 在函数返回后面+ *
//仿照int(*substract)(int a,int b)定义一个函数指针如下
int(*fun)(int a,int b)=NULL;
}
int main()
{
demoFunPoint();
return 0;
}
函数指针的使用,示例如下:
#include<stdio.h>
int sum(int a,int b)
{
return a+b;
}
int muti(int a,int b)
{
return a*b;
}
int substract(int a,int b)
{
return a-b;
}
void demoFunPoint()
{
int(*fun)(int a,int b)=sum;
int res=fun(2,5);
printf("%d\n",res);//7
}
int main()
{
demoFunPoint();
return 0;
}
函数指针数组的定义,示例如下:
#include<stdio.h>
int sum(int a,int b)
{
return a+b;
}
int muti(int a,int b)
{
return a*b;
}
int substract(int a,int b)
{
return a-b;
}
void demoFunPoint()
{
//函数指针数组的定义
int (*funs[3])(int a,int b)={sum,substract,muti};//0 1 2
int res=0;
res=funs[1](5,2);//1是substract减
printf("%d\n",res);//3
//实际应用于:界面的切换
}
int main()
{
demoFunPoint();
return 0;
}
函数指针数组的实际应用【窗口界面的切换】:
void proRun()
{
//函数指针数组的定义
int (*win_funs[30])()={loginInit,adminInit};
int winIndex = 0; //0-loginInit 1-adminInit
while(1)
{
system("cls");
winIndex = win_funs[winIndex]();
}
}
二:结构体指针[高级应用]
结构体指针的实际应用,如下,可以优化winRun函数
函数传参 WIN_T *win [结构体指针],函数内部改变,外部也可改变,无需return返回,直接设置void函数类型
函数声明:
/*
函数名称:void winRun(WIN_T *win);
函数作用:窗口运行函数 光标定位 找到edit(输入) button控件(回车,做对应操作)
函数参数:参数 WIN_T *win 窗口结构体指针
函数返回:无
*/
void winRun(WIN_T *win);
函数定义:
/*
函数名称:void winRun(WIN_T *win);
函数作用:窗口运行函数 光标定位 找到edit(输入) button控件(回车,做对应操作)
函数参数:参数 WIN_T *win 窗口结构体指针
函数返回:无
*/
void winRun(WIN_T *win)
{
int i=0,key=0;
for(i=0;i<win->ctrlCount;i++)
{
if(win->ctrlArr[i].ctrlType==EDIT||win->ctrlArr[i].ctrlType==BUTTON)
{
gotoxy(win->ctrlArr[i].startx,win->ctrlArr[i].starty);
break;
}
}
while(1)
{
key=getkey();
switch(key){
case KEY_DOWN://向下按键 查找下一个编辑框 按钮
i++;//按键数组下标越界
if(i==win->ctrlCount)
{
i=0;//为了避免下标越界 从头开始对控件结构体数组找编辑框 按钮
}
for(;i<win->ctrlCount;i++)
{
if(win->ctrlArr[i].ctrlType==EDIT||win->ctrlArr[i].ctrlType==BUTTON)//如果找到编辑框 按钮
{
gotoxy(win->ctrlArr[i].startx,win->ctrlArr[i].starty);//光标目标定位
break;//停止
}
}
break;
case KEY_UP:
i--;
if(i==-1) //从后往前找 数组起始0 i--为-1 数组下标由大到小 (控件数组下标0位置)
{
i=win->ctrlCount-1; //控件个数(控件结构体数组下标最大)-1 (控件数组下标ctrlCount位置)
}
for(;i>0;i--)
{
if(win->ctrlArr[i].ctrlType==EDIT||win->ctrlArr[i].ctrlType==BUTTON)//如果找到编辑框 按钮
{
gotoxy(win->ctrlArr[i].startx,win->ctrlArr[i].starty);//光标目标定位
break;//停止
}
if(i==0) //第一个 若第一个不是编辑框 按钮
{
i=win->ctrlCount; //就从最后一个往前查找 for循环中有i--,不用再-1
}
}
break;
case KEY_ENTER:
if(win->ctrlArr[i].ctrlType==BUTTON)
{
win->foucsIndex=i;
return ;//获取winRun中输入的编辑框的值
}
break;
default: //其他字符(不是按键)并且当前控件是编辑框
if(win->ctrlArr[i].ctrlType==EDIT)
{
editKeyListen(win->ctrlArr[i],key,win->ctrlArr[i].content);
}
break;
}
}
}
函数调用:
[需要 &取地址符]
winRun(&loginWin);
三:指针访问二维数组
重点:num[i]==*(num+i)恒等式
指针访问二维数组的两种方式:
1. nums[i][j] 数组名[行下标][列下标]
2. *(nums+i)[j] *(数组名+偏移行)[列下标]
指针 数据类型 函数传参 声明如下:
int Jude(char *name,char *pwd,USER_T userArr[]);
其中char *name //字符数组 char *pwd //字符数组 使用char * 指针数控类型
数组的定义主要有三种写法
如:char *name 、 char name[长度] 、char name[ ]
四:函数指针 & 指针函数
函数指针:是 指针存储地址,实际应用如 窗口界面的切换
指针函数如下:
//函数类型 int*作为返回
int *getAdrress(int a)
{
return &a;//指针作为返回
}
五:指针的指针
指针的指针,示例如下:
示例一:研究地址
#include <stdio.h>
void demo_point2() //指针的指针
{
int a=10;
int *pa=&a; //指针变量存储别人的地址
int **p=&pa;//指针变量也是变量,再指针变量存储别人的地址
printf("%p\n",&a);// 变量a的地址 0019FED8
printf("%p\n",pa);//指针变量pa存储a的地址 0019FED8
printf("%p\n",&pa);//指针变量也是变量,也有地址,pa的取地址:0019FED4
printf("%p\n",p); //再指针变量存储别人的地址,p存pa的地址 0019FED4
}
int main()
{
demo_point2();
return 0;
}
示例二:研究值
#include <stdio.h>
void demo_point2() //指针的指针
{
int a=10;
int *pa=&a;
int **p=&pa;
//pa的值就是a的地址,使用*取值(*p)得到a的地址
printf("%p\n",*p); //先获取变量a的地址 0019FED8
printf("%d\n",*(*p));//再取值,获取变量a的值 10
}
int main()
{
demo_point2();
return 0;
}
一个*是指针变量的地址,再来个*取值获取地址,再获取到最开始定义的值
void fun(char **name); //指针的指针
char* name = "lily";//指针变量是变量,也有地址。
char** name;//再对指针变量取值获取最终定义lily的地址进而获取lily(值)
指针的指针,使用场景:
在函数传参中,字符指针数组作为函数形参,如
void fun(char **name); 其中的char **name就是指针的指针
六:无类型指针
无类型指针定义如: void *p;
可以将任意类型的指针赋给无类型指针,但不能将无类型指针赋给其他类型指针,示例如下:
#include <stdio.h>
void demo_void()//无类型指针
{
void *p=NULL;
int a=10;
int *pa=&a;
p=pa; //可以 无类型指针接收任意类型的指针
// pa=p; //不可以 但VC不报错 void*不能直接赋值给确定类型的指针
}
int main()
{
demo_void();
return 0;
}
确定类型的指针,使用数据类型强制转换,示例如下:
#include <stdio.h>
void demo_void()//无类型指针
{
void *p=NULL;
int a=10;
int *pa=&a;
//数据类型强制转换
pa=(int*)malloc(sizeof(int)); //程序员操作的堆区
printf("%p\n",pa);//02247DC8 比较特殊 随机开辟空间 每次获取的地址都不同
}
int main()
{
demo_void();
return 0;
}
无类型指针的使用场景:void* 函数的返回,增加函数的通用性
memset的作用:为新申请的内存做初始化工作
七:const 常量指针 和 指针常量
const:修饰变量,不可以再被赋值
使用场景:不允许修改的变量或形式参数
对于strcpy()函数 可以去查看它的定义:char*, const char* 数据保护 (实际应用如抢票活动,票若是被抢完了就用户就不能再购买了)
const int num=10; //无法改变的量 值是唯一的 不能再被赋值
常量指针:地址可以修改,值不可以修改,示例如下:
#include <stdio.h>
void demo_const()
{
int a=10,b=20;
const int*p=&a; //const右边的内容不能变 常量指针
// int const *p=&a;//是同上面等价的
// p=NULL; //(指针的值)地址可修改,不能通过指针修改别人的值 NULL是void*
p=&b; //(指针的值)地址可修改,不能通过指针修改别人的值
// *p=100; // 不可以 (指针的值)地址可修改,不能通过指针修改别人的值,会报错
}
int main()
{
demo_const();
return 0;
}
指针常量:值可以修改,地址不可以修改,示例如下:
#include <stdio.h>
void demo_const()
{
int a=10,b=20;
int *const pa=&a; //指针常量
// pa=&b; //不可以,地址不可以改,会报错
*pa=100; //值可以修改
}
int main()
{
demo_const();
return 0;
}