首页 » 乱七八糟 » 对于小蓝9.22日提出的【论道】讨论结果的总结

对于小蓝9.22日提出的【论道】讨论结果的总结

由于涉及众多讨论
本贴采用时间顺序来记录事情的起因发售经过结果

起因

9月22日 10:48
小蓝在术业有转攻发表了一篇名为“有没有可能一个条件结构的两个分支都被执行?”的文章
内容十分简单:
“正方:不可能,不是true,就是false
反方:可能,不信我分分钟试一下 ”
原帖地址

------------------------------------手漂亮的工分割线------------------------------------

经过

第一阶段

10:53 - 11:27
小蓝在群里贴出了地址,吴会在马哲课上看到了并且发出了第一种解答

int main(int argc,char *argv[])
{
    int i=0;
    begin:
    if(i==0)
    {
        i=1;
        goto begin;
    }
    else
    {
    return 0;
    }
}

看到这种解答后,陈宁第一个表示了质疑“怎么还用goto”,随后又不知在何处截图,截图内容指出“在结构化程序设计中一般不主张使用goto语句, 以免造成程序流程的混乱,使理解和调试程序都产生困难。”
吴会随即反驳称,此程序结构简单不需要考虑这个。并提出了第二种解法的雏形“用循环也行”,但陈宁还是表示了坚决的反对
此时小花姐出现并发表了自己的意见,表示goto在这个地方感觉很好用啊,其余地方看情况慎用。同时小花姐还介绍了一种goto的用法给大家分享了一点人生的经验:goto一般是用来做统一出口的,很多程序会将异常出口定义在函数末尾。如果有异常分支,就用goto出去。
举例

void xx(xxx) {
xxx;
xxx;
xxx;
return;

err_out:
xxx;                  //虽然我没看goto 但是,小花姐原文是这样
xxx;                  //小花姐的意思应该将错误处理和退出写在err_out标签后
}                     //每次错误退出时都goto跳转err_out统一处理

然后小蓝不知从哪冒出来了说“用水哥的话就是,奇技淫巧”
这句话引发了小花与小蓝论战

  • 小花:“少年来给我不奇淫技巧一个?没有try catch 你准备怎么搞?”
  • 小花:“不用goto难道你准备在所有出错的分支都处理一遍?大部分程序异常退出都会释放资源等等一系列操作,你想怎么做?”
  • 小蓝:“没有try catch怪我咯?”
  • 小花:“……(你*******************************)”

好吧,回到正题
吴会表示还见过一种“把err_out定义成了宏”做为程序异常退出的的统一形式
小花姐以一个长者的身份说到“宏是一样的。。都是代码重写了。。只不过程序员不用写那么多代码 实际上预处理完代码还是重复写了很多”
然后小蓝又来BB了 “对于有逻辑洁癖强迫症的人,goto简直是!!”(所以以后还是不要写goto了,至少别让小蓝看到,免得他又发动长者的愤怒)

第二阶段

19:47

小蓝再次贴上了网址,希望大家发表一下高见,一轮新的讨论开始了
吴会再次第一个响应,“switch case算?”,小蓝甩给吴会两个字“不算”,并且表示,用switch case不用break更像语法糖
(ps.百度百科:语法糖(Syntactic sugar),也译为糖衣语法,是由英国计算机科学家彼得·约翰·兰达发明的一个术语,指计算机语言中添加的某种语法,这种语法对语言的功能并没有影响,但是更方便程序员使用。通常来说使用语法糖能够增加程序的可读性,从而减少程序代码出错的机会)
此时。。阿翔出现了,啊,不对是苏苏 她坚决的表示“喵?两个分支都执行?If肯定不行喵”(大概是目前唯一的正方观点?)
然后,小花姐再次出现了贴出了一张图:
1.png
看到了小花姐实现了之后,陈宁这小子来了句“就是酱紫”...你丫不上午还说不能用goto么.....??苏苏也发出了好棒的赞许.....你丫刚才不还说If肯定不行喵么?
回到正题,小蓝表示不服称“用goto全控已经超出范围了吧”,小花则声称“这个都好说,用gets大法”(我会告诉你我没懂?....好吧,懂的人下面回复下吧)然后小花又说“不对。。我先想想if的汇编指令是什么?”(没明白和上一句有什么联系)
小蓝还是做出了一个评价“尽管如此小花的写法还是比吴会更完(wu)美(lai)一些”
然后他又邀请了到了另一位大神——ten geek参与讨论
—— 骚年,不来一发么?
ten geek表示有点意思,参与进了讨论
这时,吴会发来了两张图:
2.jpg
3.jpg
我靠 实现了? 定睛一看,原来是switch case....完全没biger嘛 然后又被陈宁指出那个i++其实是多余的 小宁子 你成心和我作对? T T
小蓝提出了一个艾斯比问题“说了奇怪,怎么都是反方观点?” 屁!你没看见苏苏说什么了么?
当然后面又自己打自己脸了“正反方不都行么 阿翔多坚定的说绝对不行”
好吧 这时ten geek出关了,甩出了一堆代码打在小蓝脸上:

#include <stdio.h>
int main()
{
    if(1)
    {
        printf("1.\n");
        goto a;
    }else
    {
    a:
        printf("2.\n");
    }
    return 0;
}

看来简直是英雄所见略同嘛...
接下来小花姐又提出了一个方案“话说小蓝你能不能忍我在c里面嵌汇编,我强行jmp过去”,并坚决的对小蓝表示这和goto是不同的 小蓝这个反复无常的家伙又冒出来一句“我想了想,goto确实是可以,算是C语言强大的一个表现” 我只能说 你个大数据库
这时小花姐爆出了一系列新姿势

“我试了一下 if(1)和另外的条件语句编译结果不一样”
“if(1)根本不会做对比。。编译的汇编代码直接隐去了else的内容。。如果加上goto
相当于把else的内容也编译在了源码里面。。我觉得也是优化 奇怪的是。。尼玛我没开优化选项。。gcc真特喵的智能”
“不过goto还是等同于分支合并”

1.jpg
2.jpg

“我之前以为是jmp过去的。。结果不是。。”
“不过这种东西 应该是实现定义的吧。。。我这只有gcc 找个谁用vs调试看看”

然后一直潜水的蒋言斌发上了一张截图:
3.jpg
结果是vs是用jmp跳过去的
正如小花姐之前所预测:goto的汇编和编译器的定义相关
经过小花姐对文档的查询,得到了如下的结果:
4.png
自己看吧 英语不好的自行google
并且还祭出了之前吴会提到过,但没写出来的循环实现模式
5.jpg
田值大神由于参与讨论较晚,再次提出了之前说过的switch case模式
小蓝再次发表了自己的意见“懒惰写法,又或者这个更倾向map逻辑,虽然都叫判断”(完全没懂....请当事人来自行解释下吧)

这时,小花姐又来了,发了C语言的一颗语法糖
6.jpg

解释如下:[]是语法糖,因为实际实现是*(i + a)满足加法交换律啊,*(a + i)也是一样的啊(小花姐语)
用代码表示: i[a] = *(i+a) = *(a+i) = a[i]

小蓝看到跑题,表示:"I am angry" 长者的愤怒啊
然后甩出来一句:“我忽然想到怎样反驳goto了,使用goto,准确说是执行了两个分支里面的逻辑,不等于说执行了两个分支。不然你甚至可以执行1.5个”
说到这
ten geek甩了一个程序——循环模式2.0

#include <stdio.h>
int main()
{
    int c0=1,c1=0,c2=1;
    int b[]={c0,c1,c2};
    for(int i=0;i<sizeof(b)/sizeof(int);i++)
    {
        if(b[i])
        {
            printf("第%d个分支为true.\n",i);
        }
    }
    getchar();
return 0;
}

但是小蓝和吴会对这种方式表示出了不认同 这已经不是一个结构了
ten geek又说“我觉得如果遇到这种情况。完全可以一直if下去了。。”

接下来在一系列的讨论中又诞生一种新的模式——函数指针法

if(b[i]) {//这里放函数指针。} (ten geek语)
告诉你们一个方法 在分支执行的那个里面调用一个函数 然后修改函数的返回地址 使之走到另外的分支 在分支里进 入函数调用的时候。。会把函数的返回地址压入栈中。。你只要 找到那块内存并修改 让这个值变成另一个分支的入口地址。。就可以实现(小花语)

看到这些后:
“流氓啊”——小蓝
“还有更流氓的 自己实现个编译器 处理所有分支233333”——小花

小蓝最后表示他也想到了一种方法,但是否定了....fork()法
应该是

if(pid==主进程pid)
{
    printf("ture");
}
else
{
    printf("flase");
}

终于轮到小花姐了“fork已经有不同的上下文了 怎么算同一分支”

原因都是总之无论如何
也是两个都执行,但是只能算是执行了逻辑,而不是分支

------------------------------------漂亮的手工分割线------------------------------------

结果

最后总结性对话

  • 小花:“如果不用语言特性的话 正规讲 互斥的两个分支 本来就不应该能够全部执行 不然还互斥个ball 就是因为有些语言对内存有较高的控制权限 才能恶意修改正确流程 某种意义讲 是非法手段好吧 而且从应用场景上来说 没哪个逗比会把都想执行的语句放在互斥的语句里”
  • 小蓝:“难道那些辩论的题目不都是逗比的么 我反正觉得是”
  • 吴会:“那些为了辩论而辩论的辩题本身就挺逗的”
  • 苏苏:“总觉得辩论队被黑了喵”

然后:
愉快的结束........