分享
 
 
 

撒旦的语法

王朝c/c++·作者佚名  2006-01-06
窄屏简体版  字體: |||超大  

作者:Panic

很多人写代码是照猫画虎,这些“猫”最终就变成了教条(注1)。一旦教条被人熟知,不同的变量,数值,功能就被按照教条使用,然后用一些“胶水”代码组合起来,实现需要的方案。通过对语法的深入了解,我们可以消除很多的“胶水”。这篇文章举了几个怪异的C语法的例子,以及如何在不导致歧义(注2)的情况下,利用(滥用?)他们实现更高效的代码。

记得返回值

我的第一个关于“教条编程”的例子将讨论格式化输出函数sprintf。下面这段代码的写法并不鲜见:

    sprintf(str1, "Old v=%d\t",v);

    /* Some code that plays with v */

    sprintf(str2, "New v=%d",v);

    strcat(str1, str2);

    printf(str1);

大部分的sprintf实例使用一个临时的字符串变量作为它的第一个参数。这就是那个根深蒂固的教条:“sprintf需要一个临时字符串”。然而更好的教条是符合语法的,“sprintf需要一个指向字符数组的指针”。这提醒我们,可以用一个返回char *的函数替代它作为第一个参数,从而节省一个临时缓冲区的空间。例如:

    sprintf(str, "Old v=%d\t",v);

    /* Some code that plays with v */

    sprintf(strchr(str, '\0'), "New=%d",v);

    printf(str);

当直接使用指针的时候,你必须谨慎的避免NULL指针。在这个例子里,str(str,'\0')的有效得益于第一个sprintf。sprintf还隐藏了一个好处-它返回已经写入缓冲区的字符数量-这个数量可以节省一次对strlen的调用!检查你的代码吧。祝你好运!

另一个例子,如果得到一个字符串的长度,是为了在某些操作时判定它是否有效,你也许会这样写:

    len = strlen(GetFileName());

    if (len > 0)

        ; /* File name is not null */

然而,如果你只是打算用它和0比较的话,为什么不这样写:

    if (GetFileName()[0] != '\0')

        ; /* File name is not null */

这次,我们不仅节省了一个缓冲区(这很普通,我们直接使用返回值(注3)-这也避免了一次额外的拷贝),而且还在正确的检查了返回值的同时,消除了前面strlen的调用开销。别忘了,相同的结果可以用等价的方法得到。

    if (*GetFileName () != '\0')

        ; /* File name is not null */

因为字符串只是一个(可以用char * 指向的)结构,上面的方法同样可以用于返回结构体,C++类或其指针的函数,直接提取你需要的元素。例如:

    struct POINT GetCurrentPos(void);

    int y;

    y = GetCurrentPos().y;

或者,

    printf(GetDevice()->pName);

编译器可能会把结构创建为临时对象,然后把他们的指针作为隐含参数,所以你不必顾虑把结构体拷贝进栈或者出栈的开销。

从另一个角度,你还记得“函数无法返回一个字符串”的课程吗?其实你可以。方法很多。例如,创建一个名为STRING的结构体,里面包含一个字符串数组,你可以在函数中返回这样一个STRING,然后像上面那样引用其中的字符串。

    struct STRING { char str[256]; };

    struct STRING GetName(void)

    {

        .

    }

    printf(GetName().str);

实际开发中,这和传递字符串指针相比,用处很少甚至完全无益,但是它的确减少了程序员创建临时变量的需求。

表达式

函数调用只是表达式。如果他们返回一个类型(不包括void,那并不是一种真正的类型),那么你就可以把它作为一个普通的表达式用在任何需要的地方,例如一个while循环。这使得循环或者类似的流程被快速短路成为可能,从C的懒惰表达式计算中获益。(看补充)

    while (1 && GetNextLine(&str))

        ;

把表达式中的1改成0,导致整个表达式的结果变成0,GetNextLine函数不会被调用,循环永远都不会运行。我经常使用这种方法在测试代码中取消复杂的if语句块。

    if (1

        && ComplicatedExpression1

        && ComplicatedExpression2

        && ComplicatedExpression3

    )

        ;

通过把1改成全局,静态,变量,我可以在调试时,取消这些代码的运行,或者通过菜单选项改变它,从而在一次编译中测试多个项目。

结束

我希望还有一些新的想法告诉你。我忘了讲,代码也可以使用这种方式移除:

    /*

    . code here .

    //*/

然后用在首行添加一个单独的/字符来重新插入这段代码。

补充

C使用一个懒惰表达式计算器。这就是说,它只计算需要的表达式来推导最终的结果是TRUE还是FALSE,所以一行类似

    if (fn1() && fn2() && fn3())

.

的代码,会先计算fn1(),只有在必要时才继续计算fn2(),也就是说,当fn1()返回TRUE的时候。如果它返回FALSE,无论其他表达式如何,都无法使得最终结果是TRUE。大部分人从如下的代码段中凭直觉了解了这一点:

    if (ptr && ptr->Name)

        printf(ptr->Name);

这和Pascal是不同的。

译者:

本文是Steve Goodwin的大作,译者水平有限,无法很严谨的翻译文中要表达的内容,只能就个人的理解,尽量在含义上贴近原文。尽管对这篇文章的某些观点并不十分理解和赞同,但是对于开发者来说,仍然是很有价值的参考。

原文链接:http://www.gamedev.net/reference/articles/article1239.asp

注1:原文:This example becomes a template,template本意是模板,但是这里理解为教条更能表达感情的好恶。

注2:原文:without qualifying for the IOCCC (International Obfuscated C Code Contest),意译,不是很准确。

注3:原文:seeing as we use the result directly ,这里的result指的应该是函数返回值。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有