如何像计算机科学家一样思考?(C语言篇)

Mr.C/文

物格而后知至,知至而后意诚,意诚而后心正,心正而后身修,身修而后家齐,家齐而后国治,国治而后天下平。自天子以至於庶人,一是皆以修身为本。 —— 《大学》

  • 前言


早上在Instagram看到这张图片,觉得蛮有意思便转发到朋友圈,然后...
有说“写这种代码会被打”,有一脸蒙圈的,以及还有相当一部分是想把我拉黑的。

它在Ins上的评论是这样的(如果翻译得不对,请老师指正!):

  • C语言


其实,作为一名较老(cheng)司(xu)机(yuan),在推荐语言时,都会优先推荐Python,而不会推荐C。因为Python语法简单、现成的可用工具很多,关于这个问题的具体讨论可以参考 "为什么知乎上大多数人不推荐C语言入门?"

C语言的地位如何,我想TIOBE的排名可以说明,一直稳居三甲之内。(P.S. 刚查了一下,C语言八月份排名TIOBE有史(2001年)以来最低 T_T, 相关的同学要保持一颗警惕的心了。):

  • 所以,那张图到底在说什么?


图中的代码部分: void (* ( * f [] ) ( ) )( )

实际上这里定义了一个数组f[],数组中保存了未确定个函数指针,该类函数指针是指向一个返回值为void 参数为空的函数的函数指针。**(但需注意的是,在C语言的数组定义中,是需要确定数组大小的,否则编译不过) **


那到底是什么鬼?!!

咳咳,正确的打开理解方式是这样的:以“上帝版密室逃脱”为例

  • 我们在密室逃脱中,上帝给了我们一串钥匙: key = f[]
  • 这串钥匙中的任意一把可以打开其相对应的一个房间门 ** room = (* )() **
  • 打开这个房间门后,我们需要过五关斩六将(函数执行),寻找到下一关的钥匙** anotherKey**
  • 这个钥匙可以开启下一个房间门(因为我们第一次所开的门不同,此时我们所通往下一关的钥匙可能开启的是同一道门,也可能不是,这取决于上帝怎么设计。)
  • 下一个房间就是*anotherRoom = void ( ) ( ) ** ,在该房间内上帝可能放了一个惊喜也可能什么都没有。

所以,这个定义只是相当于现实生活中的一个“双层密室逃脱”而已,这样说是不是
容易理解多了?
容易理解多了?
容易理解多了?


......
......
......
好吧......

  • Talk is cheap,show me the code


Linus Torvalds said:“Talk is cheap, show me the code”。
So,我们用代码来解析一下试试看,顺便安利一下他的TED视频: 【TED】Linux 操作系统之父.

首先,定义一个房间的钥匙的类型:

 typedef void (* room_key) ();//最终房间的钥匙

然后,我们创建两个最终的房间(假设一间房里面藏有1W奖金和一间房什么都没有):

void nothing_in_the_room(void)
{ 
        printf("Sorry! You Get Nothing.\\\\n");  

}

 void something_in_the_room(void)
{ 
        printf("Congratulation! You Get Ten Thounsands.\\\\n");  

}
//这里可以注意到,这是两个返回值为void,参数为空的函数。

接下来,我们需要把上面房间的钥匙藏在另一个房间里(由于我们上面定义了两个房间,那么我们这里就需要在一个或N个房间内藏有可以开上面两个房间的钥匙,为了展示我们拥有的是一串钥匙( f[] ),这里我们定义三个房间):

room_key get_room_key1( void)
{
     room_key = nothing_in_the_room;//这里相当于把钥匙藏在该房间内,该钥匙对应的房间什么都没有
     printf( "You had got the key\\\\n ");
     return room_key;
}

room_key get_room_key2( void)
{
     room_key = something_in_the_room();//这里相当于把钥匙藏在该房间内,该钥匙对应的房间藏有1W
     printf( "You had got the key\\\\n ");
     return room_key;
}

room_key get_room_key3( void)
{
     room_key = nothing_in_the_room();//这里相当于把钥匙藏在该房间内,该钥匙对应的房间同样什么都没有
     printf( "You had got the key\\\\n ");
     return room_key;
}
//通过以上定义,我们就把上面两个房间的钥匙藏在了下面三个房间中,
//其中两个房间所藏的钥匙打开的是那间什么没有的屋子,因此我们可以认为中奖概率为1/3

**等灯邓蹬~~~ **此时我们讨论的重点该出场了,也就是我们所拥有的钥匙,它可以这样被使用:

void ( * (* f[] ) ( ) ) ( ) = {get_room_key1,get_room_key2,get_room_key3};
//这里就是我们所拥有的三把钥匙了,这三把钥匙分别藏在f[0]、f[1]以及f[2]中。

把上面的函数放到一个完整的游戏过程里面就是这样的:

void main (void)
{
    void ( * (* f[] ) ( ) ) ( ) = {get_room_key1,get_room_key2,get_room_key3};   
    //这里就是我们所拥有的三把钥匙了,这三把钥匙分别藏在f[0]、f[1]以及f[2]中。
   
    printf("Welcome To My Game! --- Mr.C\\\\n");

    int key_number = -1;//定义钥匙的编号,不同编号的钥匙对应不同的房间
    int play_times = 10;//玩家可以选择钥匙的次数
    int i = 0;

    for(i = 0; i < play_times;i++) 
    {
        printf("\\\\n=============Game Start=============\\\\n");
        printf("Please input your key number\\\\n");
        scanf(“%d",&key_number);//获取玩家输入的钥匙编码

        if ( key_number >= 0 && key_number < 3)
         {
               f[key_number]()();//通过上帝的钥匙,打开两个房间门
               /*为了便于阅读,我们可以分两步调用:
               step1:
                        room_key key = f[key_number]( );//通过第一把钥匙打开第一个房间,并获取下一把钥匙
               step2:
                        key();//通过第二把钥匙打开第二个房间门
               */
          }else {

               printf("You has not that key,I know everything.Don't cheat me\\\\n");     
                        
          } //end if      

    }// end for

}//end main

运行结果如下:

  • 结语


C语言博大精深,现在许多操作系统(大至Linux、unix,小至各Soc芯片的任务系统)或者大型项目的核心都是用C语言完成的,包括Python的核心也是C语言实现的。
但C语言的实际应用会像本文所举的例子有那么复杂么?
其实并没有,犹如上面评论所说,经常用这种充满技巧的方式写代码其实很容易被打shi的。当然,可以理解到这种复杂程度的指针个人觉得是必须而且是有一定用处的(起码比那些比较运算符优先级的题目实用多了),据说在Linux内核的网络驱动中有用到过类似本文中同一复杂程度的指针,找不到源码了,所以只能是据说了T-T.

In the end, 标题似乎定得有点大,But...

我们讲究的是,格局!格局!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,080评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,422评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,630评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,554评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,662评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,856评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,014评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,752评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,212评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,541评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,687评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,347评论 4 331
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,973评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,777评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,006评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,406评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,576评论 2 349

推荐阅读更多精彩内容

  • 指针是C语言中广泛使用的一种数据类型。 运用指针编程是C语言最主要的风格之一。利用指针变量可以表示各种数据结构; ...
    朱森阅读 3,430评论 3 44
  • 前言 把《C++ Primer》[https://book.douban.com/subject/25708312...
    尤汐Yogy阅读 9,513评论 1 51
  • Java的集合有两大类:Collection和Map,相关关系如下图: 根据上图可知Collection和Map是...
    知道越多不知道越多阅读 366评论 0 0
  • 不是天和地的两两相望而是你一转身我一眨眼 时光如任性的孩子留不住也劝不回离家久了便断了交感的根 望的穿秋水却收不回...
    文姬阅读 260评论 0 4
  • 失眠夜,拿什么拯救失落的自己。 遇见你时,我已所剩无物,我已将自己消耗得仅剩枯朽,还可以拿什么去爱你! 今...
    果丹皮_e2f6阅读 284评论 0 0