`
CB-13
  • 浏览: 21409 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

“#if 0/#if 1 ... #endif”的作用

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

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,编译器不再在红色的行给出错误提示了,编译通过,得证~_~

转自:http://www.cnblogs.com/MichaelOwen/articles/2128733.html
分享到:
评论

相关推荐

    #ifdef_#else_#endif_#if_#ifndef的用法.txt

    #ifdef_#else_#endif_#if_#ifndef的用法.txt

    #if,#endif,!defined的意义和用法

    #if,#endif,!defined的意义和用法,我在网上收集的!

    listview_5.zip

    defined(AFX_STDAFX_H__61AA8837_C4E8_11D1_B97C_783BA9000000__INCLUDED_) #define AFX_STDAFX_H__61AA8837_C4E8_11D1_B97C_783BA9000000__INCLUDED_ #if _MSC_VER >= 1000 #pragma once #endif // _MSC_VER >= ...

    #ifdef,#else,#endif和#ifndef的用法

    #ifdef,#else,#endif和#ifndef的用法

    #ifdef,#else,#endif,#if用法详解

    #ifdef,#else,#endif,#if用法详解

    头文件免费下载

    #if !defined(AFX_STDAFX_H__C4B5DA9B_21EA_47D6_9253_A4245E58FBF5__INCLUDED_) #define AFX_STDAFX_H__C4B5DA9B_21EA_47D6_9253_A4245E58FBF5__INCLUDED_ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER >...

    运动会分数统计 C++

    /*** *eh.h - User include file for exception handling. * ... All rights reserved. * *Purpose: * User include file for exception handling. * * [Public] ...#if _MSC_VER > 1000 ...#endif // _INC_EH

    ov7620用k60图像采集处理程序(双线)

    #define USOC_EN 0u //0为禁止uC/OS,大于0则启动uC/OS #if USOC_EN > 0u #include "ucos_ii.h" //uC/OS-II系统函数头文件 #include "BSP.h" //与开发板相关的函数 #include "app.h" //用户任务函数 #endif ...

    C语言 时钟

    defined(AFX_STDAFX_H__0B5A611D_24E3_40B6_A995_4850C6DC778E__INCLUDED_) #define AFX_STDAFX_H__0B5A611D_24E3_40B6_A995_4850C6DC778E__INCLUDED_ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000...

    vc StdAfx头文件

    #if !defined(AFX_STDAFX_H__58C73787_1231_40B3_A8BC_2F7670ABA3D7__INCLUDED_) #define AFX_STDAFX_H__58C73787_1231_40B3_A8BC_2F7670ABA3D7__INCLUDED_ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER >...

    VC++ 加密代码

    defined(AFX_DQPLOT_H__0D536D37_5CF1_11D1_AED1_0060973A08A4__INCLUDED_) #define AFX_DQPLOT_H__0D536D37_5CF1_11D1_AED1_0060973A08A4__INCLUDED_ #if _MSC_VER >= 1000 #pragma once #endif // _MSC_VER >= ...

    linux 下cp命令C代码实现

    #include <sys/cdefs.h> ...#if 0 static char sccsid[] = "@(#)cp.c 8.5 (Berkeley) 4/29/95"; #else __RCSID("$NetBSD: cp.c,v 1.58 2012/01/04 15:58:37 christos Exp $"); #endif #endif /* not lint */

    Libqrencode 4.0.2.rar

    #include "../Libqrencode 4.0.2/include/qrencode.h" #if _DEBUG #pragma comment(lib,"../Libqrencode 4.0.2/debug/lib.X86/LibQRd.lib") #pragma comment(lib,"../Libqrencode 4.0.2/debug/lib.X64/LibQRd.lib") ...

    D:\uC_OS-II V2.51源码

    #if (OS_EVENT_EN > 0) && (OS_MAX_EVENTS > 1) OS_EVENT *pevent1; OS_EVENT *pevent2; #endif #if OS_VERSION >= 204 OSInitHookBegin(); /* Call port specific initialization code */ #endif #if OS_TIME...

    IC卡读写仿真

    1 TEXTINCLUDE DISCARDABLE BEGIN "resource.h\0" END 2 TEXTINCLUDE DISCARDABLE BEGIN "#include ""afxres.h""\r\n" "\0" END 3 TEXTINCLUDE DISCARDABLE BEGIN "#define _AFX_NO_SPLITTER_RESOURCES\r\n...

    图像处理图像灰度增强

    数字图像处理指导程序图像处理图像灰度增强#if !defined(AFX_FIGURE_H__2830E4B2_3CD3_4E32_AD84_273816B535D0__INCLUDED_) #define AFX_FIGURE_H__2830E4B2_3CD3_4E32_AD84_273816B535D0__INCLUDED_ #if _MSC_VER ...

    学生考勤管理系统的源代码

    #include "Page1.h" // Added by ClassView #include "Page2.h" // Added by ClassView #include "Page3.h" // Added by ClassView #include "Page4.h" // Added by ClassView #if _MSC_VER > 1000 #pragma once #...

    自己创建不同规则的按钮

    #if !defined(AFX_MYSPHEREBUTTON_H__44648A94_9ABA_11D2_9E44_0020182F735A__INCLUDED_) #define AFX_MYSPHEREBUTTON_H__44648A94_9ABA_11D2_9E44_0020182F735A__INCLUDED_ #if _MSC_VER >= 1000 #pragma once #...

    rtl8188eu_parrotv1.1+ov5640验证通过RTL8188以备tinav2.1的需要_20170405_1423没有外层目录.7z

    rootroot@cm-System-Product-Name:/home/wwt/rtl8188eu_parrotv1.1/lichee$ ./build.sh config Welcome to mkscript setup progress All available chips: 0. sun8iw5p1 Choice: 0 All available platforms: 0. ...

    Visual C++课程设计案例精编(第二版)--第六章 电子邮件发送和接受程序的开发

    defined(AFX_MAILSERVER_H__CB181B60_A7D0_4663_B1F4_A97F7F2B9BAB__INCLUDED_) #define AFX_MAILSERVER_H__CB181B60_A7D0_4663_B1F4_A97F7F2B9BAB__INCLUDED_ #if _MSC_VER > 1000 #pragma once #endif // _MSC_...

Global site tag (gtag.js) - Google Analytics