搜索
bottom↓
回复: 35

C语言问题请教:看到别人的代码里有“#if 1”/“#if 0”这类肯定会执行/不执行的语句,

[复制链接]

出0入0汤圆

发表于 2008-12-30 13:43:40 | 显示全部楼层 |阅读模式
如题,还请大虾指教
个人觉得是多此一举

阿莫论坛20周年了!感谢大家的支持与爱护!!

曾经有一段真挚的爱情摆在我的面前,我没有珍惜,现在想起来,还好我没有珍惜……

出0入0汤圆

发表于 2008-12-30 13:47:15 | 显示全部楼层
是的,通常是修改代码造成的,相当于注释,或者条件编译

出0入0汤圆

 楼主| 发表于 2008-12-30 13:52:47 | 显示全部楼层
通过google,得知:
#if 0
   code
#endif

(1)code中定义的是一些调试版本的代码,此时code完全被编译器忽略。如果想让code生效,只需把#if 0改成#if 1
(2)#if 0还有一个重要的用途就是用来当成注释,如果你想要注释的程序很长,这个时候#if 0是最好的,保证不会犯错误。(但是林锐的书上说千万不要把#if 0 来当作块注释使用)
#if 1可以让其间的变量成为局部变量。
(3)这个结构表示你先前写好的code,现在用不上了,又不想删除,就用这个方法,比注释方便。

出0入0汤圆

发表于 2008-12-30 13:53:03 | 显示全部楼层
条件编译 

出0入0汤圆

 楼主| 发表于 2008-12-30 13:54:44 | 显示全部楼层
#if 1可以让其间的变量成为局部变量。
——————————————————————————————
在main()中定义的变量都是局部变量的,怎会。。。

出0入0汤圆

 楼主| 发表于 2008-12-30 13:56:24 | 显示全部楼层
是的,通常是修改代码造成的,相当于注释,或者条件编译
——————————————————————————————————————
我自己写代码是从没有这样写过,头一遭看到这样写。呵呵
不过这个条件编译也忒那个了吧,总是绝对的执行或者绝对不执行

出0入0汤圆

发表于 2008-12-30 14:35:19 | 显示全部楼层
没这样写过,可能是还没达到这个高度或深度。

有些程序牵扯太多,你又写了两种方案,但只使用一种,那另一种呢?一个个的//或/* */吗?

要是程序很大一个个子程序分步在很多的子文件中,你也这么做吗?如果下次要用另一种方案,你还记得要一个个注销那个又恢复哪些呢?

用了条件编译,这些可能只是修改一个字符的问题。这种用法在你写4K的程序时差别不大,你写一个40K的程序就知道了。

出0入0汤圆

 楼主| 发表于 2008-12-30 14:45:12 | 显示全部楼层
多谢楼上的指点~~
——————————————————————————————-
世界上总共有10种人,这个强!

出0入0汤圆

发表于 2008-12-30 14:48:45 | 显示全部楼层
MARK!

出0入0汤圆

发表于 2008-12-30 15:32:33 | 显示全部楼层
#if /#endif是C里面最重要的宏指令之一,而宏则是C的精华(C的另一精华是指针),起初是难上手,但上了手就上了贼盘,再也跑不掉的.呵呵.

#if 0 / #endif常见于调试代码.调试是将#if 0改成#if 1,代码就有效,等调完了改回#if 0,代码就等同于删除,但比删除好的是,下次要用时还可以随时再加回来---你未必能清楚知道这段代码真的可以永久删掉还是下次仍需要用.随便贴一段我写的代码,你可以看到里面有大量的条件编译:



//ICC-AVR application builder : 2005-1-21 18:37:43
// Target : MCS51 22.184    M8 8M

#include "so12864.h"

//========MCS51========================================================
#if defined(MCS51)

#include <reg51.h>
#include "so12864.h"
#include "string.h"

sbit W_IN = P3^2;
sbit W_OUT = P3^4;

#define HIGH_W_OUT W_OUT = 1
#define LOW_W_OUT W_OUT = 0

//========ATMega8========================================================
#elif defined(ATMega8)

#include <iom8v.h>
#include <macros.h>

#define W_IN (PIND & (1<<2))
#define HIGH_W_OUT PORTD &= ~(1<<3)
#define LOW_W_OUT PORTD |= (1<<3)

#endif
//========END========================================================

unsigned char w_data;                //接收时用于存储两次上升沿之间的时长,发送时存储前半周
unsigned char send_busy = 0;//存储发送时后半周
unsigned char recv_timer = 0;
unsigned char w_stat, last_w_stat;

unsigned char jiffies=0;

//========定义中断函数========================================================
#if defined(MCS51)
void clock_timer(void) interrupt 1 using 1
#elif defined(ATMega8)
#pragma interrupt_handler clock_timer:10
void clock_timer(void)
#endif
//========END========================================================
{
        //TIMER1 has overflowed 20KHz
#if defined(ATMega8)
        TCNT0 = 0xD0; //reload counter value
#endif
        if (send_busy){
                if(w_data){
                        w_data--;
                        LOW_W_OUT;
                }else{
                        send_busy--;
                        HIGH_W_OUT;
                }
        }else{
                w_stat = W_IN;
                if (w_stat != last_w_stat){
                        last_w_stat = w_stat;
                        if (w_stat){
                                w_data = recv_timer;
                                recv_timer = 0;
                        }
                }
                if (~recv_timer)//if(recv_timer != 0xff)
                        recv_timer++;
        }
        jiffies++;
}

#if defined(ATMega8)
#define RI (UCSRA & 0x80)
#define TI (UCSRA&(1<<UDRE))
#define SBUF UDR
#endif

出0入0汤圆

发表于 2008-12-30 17:58:04 | 显示全部楼层
  1、先说“#if 0/#if 1 ... #endif”的作用,楼上诸位或多或少都说到了一点,但都没有说到关键的地方。我们知道,C标准不提供C++里的“//”这样的单行风格注释而只提供“/* */”这样的块注释功能,我们通常使用它写代码中说明性的注释文字(注释作用)以及在调试时关闭某段代码对编译器的可见性(屏蔽作用),当然,这里所谓的“注释作用”和“屏蔽作用”是我们从功能上下的主观定义,对预处理器而言,两者并无任何区别。对于前者,因为“注释”中不会再出现“注释”和“需要屏蔽的代码段”,所以不会有嵌套的需求,所以通常不会有问题;而对于后者,当我们在调试程序时需要“屏蔽”某段代码时,该段代码中可能包含着前述的“注释”和/或“已被屏蔽的代码段”,这时就产生了“/* */”嵌套使用的需求,但SB的C标准恰恰不允许我们这么干。当你试图使用嵌套的块注释功能时,会发现预处理器把最外层注释的开始和最内层注释的结尾这两者之间的内容处理成了注释,而其后一直到最外层注释结尾的内容被当作了“有效代码”——这显然会引起若干语法错误而导致编译中止。高手们开动脑筋想到了“#if 0 ... #endif”,它同样由预处理器进行处理,同样可以“屏蔽”一段代码,你想把说明文字写在里面也可以,这些和“/* */”都一样,但不一样的是:第一它允许嵌套(层数上限由预处理器决定)、第二你随时可以把“#if 0”改成“#if 1”来取消对某段代码的“屏蔽”——很卓越的特性,快抛弃笨拙的“/* */”吧!它唯一的缺点就是在编辑器中没有“注释”该有的文本显示样式。

出0入0汤圆

发表于 2008-12-30 17:59:59 | 显示全部楼层
2、现在再来说说2楼提到的自动变量局部化的问题:
------------------------------------------------
通过google,得知: 
#if 0 
   code 
#endif 

(1)code中定义的是一些调试版本的代码,此时code完全被编译器忽略。如果想让code生效,只需把#if 0改成#if 1 
(2)#if 0还有一个重要的用途就是用来当成注释,如果你想要注释的程序很长,这个时候#if 0是最好的,保证不会犯错误。(但是林锐的书上说千万不要把#if 0 来当作块注释使用) 
#if 1可以让其间的变量成为局部变量。 
(3)这个结构表示你先前写好的code,现在用不上了,又不想删除,就用这个方法,比注释方便。 
------------------------------------------------

通过我上面说的第一点,我们可以知道,对“#if/#endif”的处理是预处理器完成的,而预处理器的唯一工作就是作“文字替换”的“预处理”工作,它并不负责常数符号表的生成、变量存储空间的分配、代码的重定位等工作,那么完全是给预处理器看的“#if/#endif”怎么能控制变量的生存期、怎么能决定变量可以在哪里定义??
打开编辑器,写下如下代码:
===========================
volatile unsigned char a;
unsigned int main(void)
{
        a = 0;
#if     1
        unsigned char *p = &a;
        *p = 255;
#endif
        return 0;
}
===========================
存成.c文件后用任何C编译器(不包括C++编译器)编译,都会在红字那一行报错——为什么呢?因为预处理器进行“预处理”的时候发现if的条件表达式为“真”,所以它把那段代码块留下了,而只把代码块前后的“预处理指示符号(或者叫做预处理命令)”给清除掉了,这样,预处理后的结果交给编译器“翻译”的时候,它发现在一个函数(在这里为main函数)内部的表达式语句(在这里是a = 0;)之后发现了变量声明/定义语句(在这里是声明并定义指针变量p的语句)——按照编译器的规则,这是一个错误,所以它拒绝接受这样的输入、罢工并开始抱怨(中止编译、给出错误信息)。

至此,关于“#if 1/#if 0/#endif”,我要说的就全说完了,欢迎大家拍砖哈~_~


下面再多啰嗦两句。
--------------------------
那么我们能不能享受C++程序员所得到的“将变量的定义放在它开始被需要的地方”这种待遇呢?
答案是肯定的。
手段?
——代码块!

  用一对大括号括起来的代码块的首部,可以声明/定义变量,这些变量的作用域仅限于该代码块内部,当然,这些变量声明/定义语句也必须全部位于该代码块中第一个表达式语句之前,不然会出现上面描述的错误,不过好在C编译器允许我们在代码块中嵌套定义代码块,所以大家从现在开始,大可不必在函数的开头定义一大堆变量,那里只要写一些在整个函数执行过程当中都需要的变量的声明/定义语句就好了;至于循环结构的循环变量等这些生存期不长的变量,它们的声明/定义语句完全可以放在一个用一对大括号括起来的代码块的首部。
  啰嗦了这么多,写一小段代码证明一下我的说法,呵呵:
===========================
volatile unsigned char a;
unsigned int main(void)
{
        a = 0;
        {       //
        unsigned char *p = &a;
        *p = 255;
        }
        return 0;
}
===========================
  注:我个人的代码书写风格是大括号独占一行并且缩进量与父语句相同,函数体、循环体、case、if四者中的语句增加缩进,但如上的“代码块”则不增加。
存盘、编译。
Hmmmm,编译器不再在红色的行给出错误提示了,编译通过,得证~_~
再次小声说一句:欢迎拍砖~~

本贴被 eduhf_123 编辑过,最后修改时间:2008-12-30,23:15:19.

出0入0汤圆

发表于 2008-12-30 18:14:15 | 显示全部楼层
C99支持  //斜杠注释的。

出0入8汤圆

发表于 2008-12-30 18:16:21 | 显示全部楼层
我以前不敢用块注释/* */,因为其不能嵌套,还以为C怎这么RZ!
自从用上了#if 0,嘿嘿

出0入21汤圆

发表于 2008-12-30 18:58:45 | 显示全部楼层
好贴。

出0入0汤圆

发表于 2008-12-30 19:23:24 | 显示全部楼层
【13楼】 rube 永丰庵
积分:1317
派别:
等级:------
来自:深圳
 我以前不敢用块注释/* */,因为其不能嵌套,还以为C怎这么RZ! 
自从用上了#if 0,嘿嘿  
   


我也是.被/* */搞得烦死了,经常COPY代码时COPY出问题来.
话说回来,用#if 来注释掉代码的确是"歪打中着",估计#if的发明者做梦都没想到过它还有这功能,哈哈.

出330入0汤圆

发表于 2008-12-30 22:21:42 | 显示全部楼层
到此一游,满载而归

出0入0汤圆

发表于 2008-12-30 22:34:22 | 显示全部楼层
其实我经常两个一起用
#if 0 不是太短了吗?眼睛对这个短文本不敏感,把/*  */也放上

#if 0
/*********XXXXXXXXXXXXXXX*******************/

......

.....

/*********XXXXXXXXXXXXXXX*******************/
#endif

两全其美

出0入0汤圆

发表于 2008-12-30 22:46:11 | 显示全部楼层
学习一下..

出0入0汤圆

发表于 2008-12-30 23:29:38 | 显示全部楼层
【12楼】 mljda 技术是人性

积分:1911
派别:
等级:------
来自:全国各地

 C99支持  //斜杠注释的。  
__________________________ 

是的,这个我知道,不止C99支持,很多尚不支持C99标准的“扩展的”C编译器所带的预处理器都是支持双斜杠型单行注释的。
可是:
1、C99现在还未成为通用的事实标准;
2、不支持C99但支持双斜杠型单行注释的,只能算是编译器对标准C的扩展,它们代替不了标准,(上一版)标准C确实是不支持的;
3、不是要抬杠或争辩什么,我帖子里这样说只是为了引出下文,可能承接没有做好~_~
4、(嗯,这个算P.S.)在坛子里潜水有一段时间了,早就想认识一下、交个朋友了,呵呵~~

出0入0汤圆

发表于 2008-12-31 00:49:06 | 显示全部楼层
【17楼】 robinyuan 

积分:398
派别:
等级:------
来自:
 其实我经常两个一起用 
#if 0 不是太短了吗?眼睛对这个短文本不敏感,把/*  */也放上 

#if 0 
/*********XXXXXXXXXXXXXXX*******************/ 

...... 

..... 

/*********XXXXXXXXXXXXXXX*******************/ 
#endif 

两全其美  
__________________________

使用如下的形式,可以少占用一行:
#if 0x0000000000000000000000000000000000000000
.
.
.
#endif /*XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX*/

另外,印象当中记得,SourceInsight仿佛可以把上面的代码块“收起/展开”?

出0入0汤圆

发表于 2008-12-31 08:34:29 | 显示全部楼层
呃,编辑器不同而已,用eclipse试试,连 #if 不是有效的文本也颜色标注了,很方便。

出0入0汤圆

发表于 2008-12-31 08:57:38 | 显示全部楼层
不错,学到东西了

出0入0汤圆

 楼主| 发表于 2009-1-4 10:38:08 | 显示全部楼层
多谢楼上各位~~

出0入0汤圆

发表于 2011-11-21 10:56:35 | 显示全部楼层
回复【11楼】eduhf_123 经历
-----------------------------------------------------------------------
第一个看懂了,第二个没明白,大师能不能讲得详细点?THANKS

出0入0汤圆

发表于 2011-12-20 13:34:35 | 显示全部楼层
好贴,直到今天还在造福人类,哈哈。

出0入0汤圆

发表于 2011-12-20 13:46:09 | 显示全部楼层
块注释:
IAR直接用 CTRL+K

块移除注释:
IAR直接用 CTRL+SHIFT+K

出0入0汤圆

发表于 2011-12-20 17:17:11 | 显示全部楼层
这就是传闻中的“剪裁” ...

出0入0汤圆

发表于 2012-3-24 16:11:28 | 显示全部楼层
学习了,呵呵! mark!

出0入0汤圆

发表于 2012-9-11 15:05:10 | 显示全部楼层
“#if 0/#if 1 ... #endif”的作用

出0入0汤圆

发表于 2012-9-13 20:01:44 来自手机 | 显示全部楼层
记号一下.............

出0入0汤圆

发表于 2013-4-8 20:43:00 | 显示全部楼层
mark........................

出0入0汤圆

发表于 2013-6-23 18:03:22 | 显示全部楼层
有用

出0入0汤圆

发表于 2013-6-23 23:18:18 来自手机 | 显示全部楼层
正须要这样的注释方法。

出0入0汤圆

发表于 2013-6-24 08:51:21 | 显示全部楼层
这个功能好啊。
为什么楼上所有的空格都就成了 。
这个东西让人看的头晕啊。

我被别人程序中的一堆/**/都要弄烦了。
有了这个if空格0,endif,if空格1,endif.就方便多了。
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-8-26 23:24

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表