char data1[5];
char *p1 = data1;
float data2[5];
float *p2 = data2;
char data4[4][5];
char (*p4)[5] = data4;
char *data5[5];
char* *p5 = data5;
char (*data6[5])[6];
char (*(*p6))[6]= data6;
一、函数名的本意
1、函数名的本质
数组名、函数名==常量的地址,连续空间的首地址
函数名无法按照字节方式访问,CPU的PC决定访问方式(函数方式访问)
int (*p)(const char *,...) = printf;//...不定参数,压栈
printf("%p\n",printf);
printf("%p\n",p);
p("hello\n");
要求设置一绝对地址为0x67a9的整形变量的值为0xaa66
int *p = (int *)0x67a9;
*p = 0xaa66;
设计一个代码,让CPU到0x20008000的位置上执行
(void (*)(void) )0x20008000
( (void (*)(void) )0x20008000 )()
void (*fun)(void) = (void (*)(void) )0x20008000;
fun()
typedef void (*handler)(void)//(handler是一个输入参数void返回值为void的)地址的变量
typedef void (*handler)(void)//(handler是一个输入参数void返回值为void的)地址的别名
handler fun = (handler)0x20008000
fun()
int (*p)(const char *) = (int (*)(const char *) )printf
typedef int (*show_t)(const char *,...)
show_t myshow = (show_t)printf;
myshow("hello\n");
2、函数形参执行顺序
形参:实现功能者为了接收调用者传来的信息,临时分配一段区域来接收
实参:调用者分配处的空间
3、函数的承上启下
承上启下 :获取信息 反馈信息
二、函数接收信息方式
函数思想:模块化设计的思想--模块如何组合在一起
如果设计子模块,是的其他模块可以方便组合
子模块需要接收上层模块发出的地址才能对发出的地址进行操作
fop(a);
fop(&a);
三、子模块修改地址变量的方法
上层空间,需要子模块来修改
1、调用者 必须把这个空间的首地址传递过去
2、子模块设计者 必须通过这个地址反向查找进行更新
函数传递了地址:
1、子模块具有了修改上层空间的能力
2、子模块可以连续访问首地址的内容(看/改)
a、看连续的空间 void fun(const int *p,int len)
b、看一个数据类型 void fun (int p)
c、改连续空间 void fun (int *p,int len)
d、改一个数据类型 void fun (int *p)
统计字符空间中空格的个数
int cntSpace(const char *str){}
删除字符空间中空格的个数
void cntSpace( char *str){}
字符空间已更改,是否返回根据实际需求
strcpy有返回值,方便与链式调用,这个函数的返回值是另外一个函数的输入参数
strlen( strcpy( buf,"hello" ) )
四、任务查找框架
代码--数据 分离思想 耦合度降低
维护操作符与函数名相对应的一张表
操作符 函数名
+ my_add()
- my_sub()
* my_mul()
/ my_div()
类似于一个结构体
struct data_tab{
char op;
int (*handler)(int ,int)
};
struct data_tab table[4] = {};
#include<stdio.h>
int conver(char *str){
int res = 0;
int n = 0;
while( *str ){
if( !( (*str >= '0') && (*str <= '9') ) ){
break;
}
n = *str - '0';
res = res * 10 + n;
str ++;
}
return res;
}
int my_add(int n1,int n2){
return n1+n2;
}
int my_sub(int n1,int n2){
return n1-n2;
}
int my_mul(int n1,int n2){
return n1*n2;
}
int my_div(int n1,int n2){
return n1/n2;
}
//定义一个操作符和操作函数的表格
typedef struct {
char op;
int (*handler)(int ,int);
}My_Tab;
My_Tab data[] = {
{ '+',my_add },
{ '-',my_sub },
{ '*',my_mul },
{ '/',my_div },
};
int main(int argc,char *argv[]){
int num1 = 0;
int num2 = 0;
int result = 0;
int i = 0;
// if( argc != 4 ){
if( argc > 4 ){
printf("Usage:输入个数多了\n");
return -1;
}
else if( argc < 4){
printf("Usage:输入个数少了\n");
return -1;
}
num1 = conver(argv[1]);
num2 = conver(argv[3]);
printf("num1 = %d, num2 = %d\n",num1,num2);
for( i = 0; i < sizeof(data)/sizeof(data[0]); i ++){
if( (data[i].op == argv[2][0]) && (data[i].handler) ){
result = data[i].handler(num1,num2);
break;
}
}
if( i == sizeof(data)/sizeof(data[0]) ){
printf("输入错误\n");
return -1;
}else{
printf("%d\n",result);
}
return 0;
}
五、stroul的使用
头文件:#include<stdlib.h>
atoi--只能进行转换,不能查找错误
strtol--能通过返回指针来确定是否转换错误
int main(){
const char *p = "123abc";//const char *p = "123";
char *x;
int res = strtol(p, &x,10);
printf("%p,%x",x,x[0]);
printf("res = %d\n",res);
return 0;
}