1.如何用C语言实现一个函数,传递两个整形数,返回两个数的和?

#include<stdio.h>

int add(int a,int b)
{
return a+b;
} void main()
{
int a=,b=;
printf("a=%d\nb=%d\nResult=%d",a,b,add(a,b));
getchar();
}

2.同时计算两个数的和与差?

#include<stdio.h>

int add(int a,int b)
{
return a+b;
} int sub(int a,int b)
{
return a-b;
} void main()
{
int a=,b=;
printf("a=%d\nb=%d\na+b=%d\n\n",a,b,add(a,b));
printf("a=%d\nb=%d\na-b=%d\n\n",a,b,sub(a,b));
getchar();
}

  现在你所写软件已经具备加法和减法功能。要知道,人的欲望无穷无尽……

3.提供一个函数,使得我在加法完成之后做一些事情(必须要在函数加法函数返回之前做),比如打印结果,修改结果。 

#include <stdio.h>

int add(int a,int b)
{
return a+b;
} //提供一个可以在add之后随意做点事情的函数
//为了修改值,所以需要传递变量的指针
//函数传递了一个函数指针,其原型为:int (*)(int *)
int addAfterDoSomething(int a,int b,int (*AddAfter)(int *result))
{
int resutl = add(a,b);
AddAfter(&resutl);
return resutl;
} //要在add之后修改其值
int changeValue(int * value)
{
printf("Value Before Change : %d\n",*value);
*value = *value -;
printf("Value After Change : %d\n",*value);
} void main()
{
int a=,b=;
printf("a=%d\nb=%d\nResult=%d",a,b,addAfterDoSomething(a,b,changeValue));
getchar();
}

4.提供一个函数,使得我在加法完成之后做一些事情(必须要在函数加法函数返回之前做)之后,再做一些事情。

//是的正如你所想,局势在函数最后面再加一个函数指针
int addAfterDoSomething(int a,int b,int (*AddAfter)(int *result),int (*AddAfterAfter)(int *result))

5.提供一个函数,使得我在加法完成之后做一些事情(必须要在函数加法函数返回之前做)之后,再做一些事情之后,再做一些事情。

int addAfterDoSomething(int a,int b,int (*AddAfter)(int *result),int (*AddAfterAfter)(int *result),int (*AddAfterAfterAfter)(int *result))

  正如你所看,对于一个追求完美的人,上面黄色背景的那一串函数原型,太碍眼,太丑陋,看起来太复杂,太让人接受不了。

6.美化第3步的代码

//省略若干

#ifndef DoSomethingAfterAdd
#define DoSomethingAfterAdd int (*AddAfter)(int *result)
#endif //省略若干
//将
int addAfterDoSomething(int a,int b,int (*AddAfter)(int *result))
//替换为
int addAfterDoSomething(int a,int b,DoSomethingAfterAdd);

7.美化第四步的代码

//省略若干

#ifndef DoSomethingAfterAdd
#define DoSomethingAfterAdd int (*AddAfter)(int *result)
#endif //省略若干
//将
int addAfterDoSomething(int a,int b,int (*AddAfter)(int *result))
//替换为
int addAfterDoSomething(int a,int b,DoSomethingAfterAdd,DoSomethingAfterAdd);
//很明显,这样通不过编译!
//Error:重复的参数名

 正确的方法如下:

//定义一个带有参数的宏
#ifndef DoAfter(X)
#define DoAfter(X) int (*X)(int *result)
#endif //在编译代码时,编译器会将DoAfter(AddAfter)翻译为int (*AddAfter)(int *result)
//同理,DoAfter(AddAfterAfter) ==int (*AddAfterAfter)(int *result)
int addAfterDoSomething(int a,int b,DoAfter(AddAfter),DoAfter(AddAfterAfter));

   参考:https://gcc.gnu.org/onlinedocs/cpp/Macro-Arguments.html

8.美化第5步

//当然非常简单了……
int addAfterDoSomething(int a,int b,DoAfter(AddAfter),DoAfter(AddAfterAfter),DoAfter(AddAfterAfterAfter))
{
int resutl = add(a,b);
AddAfter(&resutl);
AddAfterAfter(&resutl);
AddAfterAfterAfter(&resutl);
return resutl;
}

9.美化第八步

//定义一个自定义类型FunAddAfter
//类型的值为一个指向函数的指针
typedef int(* FunAddAfter)(int *Result); //可以像使用int类型一样使用FunAddAfter
int addAfterDoSomething(int a,int b,FunAddAfter AddAfter,FunAddAfter AddAfterAfter,FunAddAfter AddAfterAfterAfter)
{
int resutl = add(a,b);
AddAfter(&resutl);
AddAfterAfter(&resutl);
AddAfterAfterAfter(&resutl);
return resutl;
} void main()
{
int a=,b=;
//在使用自定义类型时,需要像其他类型一样声明,赋值,然后使用 -.-废话
FunAddAfter change;
//函数名其实也就是一个指针,指向函数的地址
  change = changeValue;
printf("a=%d\nb=%d\nResult=%d",a,b,addAfterDoSomething(a,b,change));
getchar();
}

  到这里如果说teypdef的作用也就是美化的话,那么#define完全可以胜任所有的工作。

10.实现一个函数,使得可以在加法运算后执行若干个,未知个数个其他事情  

/定义一个自定义类型FunAddAfter
//类型的值为一个指向函数的指针
typedef int(* FunAddAfter)(int *Result); typedef struct _funList
{
FunAddAfter node;
struct _funList * nextNode;
} FunList,*PFunList; //仅仅打印值
int printfValue(int * value)
{
printf("the Value is :%d\n",*value);
return *value;
} //计算一个数的平方
int Squre(int * value)
{
printf("Squre value :%d is %d\n",*value,(*value)*(*value));
return *value=(*value)*(*value);;
} int DoManythingAfterAdd(int a, int b ,PFunList funlist)
{
int result = add(a,b);
while (NULL!=funlist)
{
result = funlist->node(&result);
funlist = funlist->nextNode;
}
return result;
} void main()
{
int a=,b=;
//在使用自定义类型时,需要像其他类型一样声明,赋值,然后使用 -.-废话
FunAddAfter change,squreValue,printvalue;
PFunList funlistHead,funListNode1,funListNode2;
//函数名其实也就是一个指针,指向函数的地址
change = changeValue;
squreValue=Squre;
printvalue = printfValue;
funlistHead =(FunList *) malloc(sizeof(FunList));
funListNode1 =(FunList *) malloc(sizeof(FunList));
funListNode2 =(FunList *) malloc(sizeof(FunList));
funlistHead->nextNode = funListNode1;
funlistHead->node = change;
funListNode1->nextNode = funListNode2;
funListNode1 ->node = printvalue;
funListNode2 ->node = squreValue;
funListNode2 ->nextNode = NULL;
printf("a=%d\nb=%d\nResult=%d",a,b,DoManythingAfterAdd(a,b,funlistHead));
getchar();
}

总结typedef的作用

1.满足Geek的简洁代码需求——正如你所看到的,函数的功能其实也可以通过一长串的函数原型来实现,或者使用宏定义,我也可以不使用typedef来完成功能,但是对于追求卓越的人,容忍不了看起来太长和复杂的函数定义

2.满足Geek的控制欲——除了C标准提供的基本类型,我也要定义一个自己的公司内部使用的类型,在公司不得使用int,而一定要使用tianchaoweida

typedef int tianchaoweida;

3.因为tepedef能定义自定义类型,所以就能够超越#Define,有自己独特存在的理由!如下:

FunAddAfter change,squreValue,printvalue;

源码下载

一步步理解typedef的更多相关文章

  1. 深入理解typedef

    首先请看看下面这两句:                  typedef int a[10];                  typedef void (*p)(void); 如果你能一眼就看出它 ...

  2. 理解typedef(转)

    // 从别人那转的,调整下格式便于阅读. 首先请看看下面这两句: typedef ]; typedef void (*p)(void); 如果你能一眼就看出它们的意思,那请不要再往下看了.如果你不太理 ...

  3. 如何理解typedef void (*pfun)(void)

    问题: 在刚接触typedef void (*pfun)(void) 这个结构的时候,存在疑惑,为什么typedef后只有一"块"东西,而不是两"块"东西呢?那 ...

  4. 函数指针-如何理解typedef void (*pfun)(void)

    问题: 在刚接触typedef void (*pfun)(void) 这个结构的时候,存在疑惑,为什么typedef后只有一"块"东西,而不是两"块"东西呢?那 ...

  5. 我是这样一步步理解--主题模型(Topic Model)、LDA

    1. LDA模型是什么 LDA可以分为以下5个步骤: 一个函数:gamma函数. 四个分布:二项分布.多项分布.beta分布.Dirichlet分布. 一个概念和一个理念:共轭先验和贝叶斯框架. 两个 ...

  6. 一步步理解linux字符设备驱动框架(转)

    /* *本文版权归于凌阳教育.如转载请注明 *原作者和原文链接 http://blog.csdn.net/edudriver/article/details/18354313* *特此说明并保留对其追 ...

  7. 通过100张图一步步理解CNN

    https://blog.csdn.net/v_july_v/article/details/79434745 Youtube上迄今为止最好的卷积神经网络快速入门教程 https://www.bili ...

  8. NRF51822+STM32bootload——typedef void (*Fun) (void) 理解

    1.typdef 用法如下所示 typedef unsigned char uint8_t; typedef unsigned short int uint16_t; typedef unsigned ...

  9. C语言语法 typedef小结

    在总结typedef之前,先了解一个专业术语: 常量指针(const pointer):常量指针在定义的时候必须被初始化,而且一旦初始化完成,则它的值就不能再改变. int errNumb = 0; ...

随机推荐

  1. P4177 [CEOI2008]order 最小割

    \(\color{#0066ff}{ 题目描述 }\) 有N个工作,M种机器,每种机器你可以租或者买过来. 每个工作包括若干道工序,每道工序需要某种机器来完成,你可以通过购买或租用机器来完成. 现在给 ...

  2. P2962 [USACO09NOV]灯Lights 对抗搜索

    \(\color{#0066ff}{题目描述}\) 贝希和她的闺密们在她们的牛棚中玩游戏.但是天不从人愿,突然,牛棚的电源跳闸了,所有的灯都被关闭了.贝希是一个很胆小的女生,在伸手不见拇指的无尽的黑暗 ...

  3. powdesigner建表

    默认打开powerDesigner时,创建table对应的自动生成sql语句没有注释. 方法1.comment注释信息 在Columns标签下,一排按钮中找到倒数第2个按钮:Customize Col ...

  4. 使用lombok 简化代码

    第一步:添加依赖 第二步:下载 lombok  jar 包 第三步 :打开cmd 命令行 执行命令, -javaagent:lombok.jar -Xbootclasspath/a:lombok.ja ...

  5. void类型指针的基本用法

    void作为指针时可以用任意类型的的指针值都可以给它进行赋值和传递,但是输出时必须时显性输出 代码如下: #include<cstdio> #include<iostream> ...

  6. Photoshop入门教程(五):滤镜

    学习心得:滤镜通常用于摄影行业,是安装在相机镜头前用于过滤自然光的附加镜头,从而获得一些特殊的效果.同理,Photoshop的滤镜也是为了产生特殊的效果.Photoshop滤镜分为两类:一种是内部滤镜 ...

  7. Redis未授权访问反弹shell

    Redis未授权访问反弹shell 目标主机:10.104.11.178 攻击机:kali 攻击步骤: 1.与目标主机连接 root@kali:~# /usr/redis/redis-cli -h 1 ...

  8. shematool -initschema -dbtype mysql error org.apache.hadoop.hive.metastore.hivemetaexception:Failed to get schema version

    命令:schematool -initSchema -dbType mysql Fix the issue: edit /etc/mysql/my.cnf change bind-address   ...

  9. ssis error at other ssis.pipeline "ole db destination" failed validation and returned validation status

    我在修改一个ssis的包,发现这个destination的表被改过了.所以就重建了表.就导致了这个错误. 打开包重新检查下表结构的匹配就好了

  10. vscode写vue模板--代码片段

    Ctrl+Shift+P打开命令输入 snippet (打开用户代码片段) 在输入vue(选择代码片段的语言) 如果搜索不到,安装一个插件 vueHelper 如果搜索到复制粘贴以下代码 { &quo ...