请问 #if..... #php endiff可以用来注释,是吗?这个代码到底是用来做什么

今天在看程序时,发现一个函数中使用的很多的
因为没有用过,感到有点莫名。如是上网查找答案。终于明白是用来注释编译内容的。意思是说:
需要编译器编译以下内容;
编译器不要编译以下内容;
这种用法还可以实现“注释嵌套!!!”//如果用的话,中间的代码不能加注释。这样不利于调试。
void Time_Display(u32 TimeVar){#if 1
u32 TY = 0, TM = 1, TD = 0;
s32 Num4Y,NumY, OffSec, Off4Y = 0;
s32 NumD //OffD#endif
u32 THH = 0, TMM = 0, TSS = 0;#if 0
THH = TimeVar/3600;
TMM = (TimeVar % 3600)/60;
TSS = (TimeVar % 3600)% 60;#endif#if 1
Num4Y = TimeVar/SecsPerFourY
OffSec = TimeVar%SecsPerFourY
while(OffSec & Year_Secs_Accu[i++])
NumY = Num4Y*4 + Off4Y;
TY = 2000+NumY;
OffSec = OffSec - Year_Secs_Accu[i-2];
while(OffSec & Month_Secs_Accu_C[i++]);
OffSec = OffSec - Month_Secs_Accu_C[i-2];
// leap year
while(OffSec & Month_Secs_Accu_L[i++]);
OffSec = OffSec - Month_Secs_Accu_L[i-2];
NumDay = OffSec/SecsPerD
OffSec = OffSec%SecsPerD
TD = NumDay+1;
THH = OffSec/3600;
TMM = (OffSec % 3600)/60;
TSS = (OffSec % 3600)% 60;
printf("Date: %0.4d-%0.2d-%0.2d Time: %0.2d:%0.2d:%0.2d\r",TY, TM, TD,THH, TMM, TSS);}
C语言中#if 0,#if 1,#else,#endif的作用
在C语言中时常会用到#if 0,#if 1,#else,#endif语句,语句如下所示:
此时code1的语句...
#if #endif
1.if EXPLICIT_DEVICE_ID
Uint16 APPL_GetDeviceID()
return 0xBABA;
如何解释EXPLICIT...
#if、#elif、#else 和 #endif 指令详解 (C/C++)
#if、#elif、#else 和 #endif 指令详解 (C/C++)#if 指令与 #elif、#else 和 #endif 指令一起控制源文件部分的编译。 如果您编写的表达式(在 #if 后)...
C语言#ifdef,#else,#ifndef,#error等用法
在写#error之前顺便学习习其他预定义的方法
#endif #ifndef等(英语不好,打印的提示不规范,勿笑话)
有如下程序
main(void)...
#if #else #endif 的应用
有些程序在调试、兼容性、平台移植等情况下可能想要通过简单地设置一些参数就生成一个不同的软件,这当然可以通过变量设置,把所有可能用到的代码都写进去,在初始化时配置,但在不同的情况下可能只用到一部分代码,...
第一它允许嵌套(层数上限由预处理器决定)、第二你随时可以把“#if0”改成“#if 1”来取消对某段代码的“屏...
块注释符(/*...*/)是不可以嵌套使用的。我们还可以使用 #if 0 ... #endif 来实现注释,且可以实现嵌套,格式为:#if 0
#endif 你可以把 #if 0 改成...
#ifdef的用法
灵活使用#ifdef指示符,我们可以区隔一些与特定头文件、程序库和其他文件版本有关的代码。
代码举例:新建define.cpp文件
今天刚发布的新版本,运营的突然跑我那说:为什么咱们的应用还没审核通过,为什么添加的友盟的事件统计都有数据了呢,仔细研究了一下发现友盟统计是这个样子的:只读工程里面的设置,默认是App Store;所以...
A typical web developer knows exactly how a PHP if statement looks like:
没有更多推荐了,c语言关于#if...#endif调试。_百度知道
c语言关于#if...#endif调试。
#defineDEBUG1#ifDEBUG==1调试代码#endif起到了调试作用,但直接compile不也行么?...
#define DEBUG 1#if DEBUG==1调试代码#endif起到了调试作用,但直接compile不也行么?
答题抽奖
首次认真答题后
即可获得3次抽奖机会,100%中奖。
采纳数:1370
获赞数:4462
如果你不想compile这段调试代码时,你只需要将#define DEBUG 1修改为#define DEBUG 0就行,这样可以省很多麻烦。这个就叫做条件编译。
I_lovetennis
I_lovetennis
采纳数:19
获赞数:57
擅长:暂未定制
这是条件编译,如果DEBUG的宏定义为1那么编译下面内容,否则,下面内容不编译,这样写是方便调试
为你推荐:
其他类似问题
个人、企业类
违法有害信息,请在下方选择后提交
色情、暴力
我们会通过消息、邮箱等方式尽快将举报结果通知您。#program 与 #ifndef #endif区别
在用VC6.0向导生成的头文件中,经常可以看见如下的代码段:
#ifndef AFX_RESIZABLELAYOUT_H__INCLUDED_
#define AFX_RESIZABLELAYOUT_H__INCLUDED_
#if _MSC_VER & 1000
#pragma once
#endif // _MSC_VER & 1000
#endif // !defined(AFX_RESIZABLELAYOUT_H__INCLUDED_)
对于宏有基本了解的朋友应该都知道,头文件中如下的宏定义,是为了避免同样的头文件在同一个.C文件或者.CPP文件多次包含。
#ifndef XXX
#define XXX
这很好理解,但接下来的一段,尤其是#pragma once的意思,我就不是很清楚了。从MSDN得到pragma once的解释是:
"Specifies that the file will be included (opened) only once by the compiler when compiling a source code file."
英文注释的大意也是说#pragma once是为了避免文件重复包含。疑惑就此产生了,既然宏"#ifndef"已经有这个作用了,为何还要一个"#pragma once"呢? 我接着在网上搜到了几份答案,但大家的回答都很模糊,于是我想放弃,不再想这个问题,但还是不太甘心,就接着看了看别人的解释。突然间,好像灵犀一点,开窍了。虽然"#ifndef"和"#pragma once"都有避免重复包含的功能,但是在实现上还是有区别的。举一例如下:
// Test1.h
#ifndef __TESTONE_H_
#define __TESTONE_H_
// Test2.h
#pragma once
// Test.cpp
#include "Test1.h"
#include "Test1.h"
#include "Test2.h"
#include "Test2.h"
头文件Test1.h中用宏来避免重复,头文件Test2.h中用#pragma once来避免重复。编译Test.cpp,将需要打开Test1.h两次,第一次发现宏__TESTONE_H_没有定义,接着就处理宏定义;第二次打开Test1.h时,发现宏__TESTONE_H_已经定义过了,编译器就会略过宏定义部分,知道处理完Test1.h末尾的#endif。
而由于头文件Test2.h使用#pragma once来避免重复定义的,在编译Test.cpp的过程中,Test2.h只会被打开一次,也就是处理到第3行的时候。因为Test2.h用的是#pragma once,所以在处理完第3行后,编译器已经知道包含了一次Test2.h,在它(编译器)处理第4行代码时,发现Test2.h已经包含过了,忽略掉第 4行代码,也就不需要再次打开Test2.h进行判断了。
总结一下,除了#pragma once是微软编译器所特有的之外,用宏和#pragma once的办法来避免重复包含头文件,主要区别在于宏处理的方法会多次打开同一头文件,而#pragma once则不会重复打开,从而#pragma once能够更快速。
详解#program
C和C++的每个实现对它的主机或操作系统都支持一些独有的特征。例如,某些程序须对存放数据的存储器区域进行精确的控制,或必须控制特定函数接受参量的方式。#pragma指令对每个编译器给出了一个方法,在...
#ifndef 与 #program once 的区别
(转)#ifndef 与 #program once 的区别
分类: vc++编译运行错误|字号 订阅
来自:h...
C语言中#ifdef,#ifndef和#endif的作用
1、用于注释掉一段代码
我们自己编写程序的时候,需要看到一系列的调试代码,但是发给客户的时候,客户可不希望看到什么什么OK的代码,所以我们希望能很容易地注释掉这段代码。
这时需要用到预处理指令 #...
#ifndef 与 #program once 的区别 和注意点
来自:http://blog.csdn.net/jfkidear/article/details/7868662
为了避免同一个文件被include多次,C/C++中有两种方式,一种是#ifndef...
#ifndef到底什么意思?
看了网上别人的文章,以前对ifndef的含义一直有些困惑。现在终于明白了。以下文件在&os_cpu.h&中。#ifndef __OS_CPU_H__#define __OS_CPU_H__ /*中间有...
#ifndef的用法
头件的中的#ifndef,这是一个很关键的东西。比如你有两个C文件,这两个C文件都include了同一个头文件。而编译时,这两个C文件要一同编译成一个可运行文件,于是问题来了,大量的声明冲突。
c语言中的#ifndef、#def、#endif等宏是什么意思
#ifndef、(或者#ifndef)、#def、#endif等宏这几个宏是为了进行条件编译。一般情况下,源程序中所有的行都参加编译。但是有时希望对其中一部分内容只在满足一定条件才进行编译,也就是对一...
C语言进阶-ifndef的用法
1、ifndef是 if not define 的缩写
#ifndef x //先测试x是否被宏定义过
程序段1 //如果x没有被宏定义过,定义x,并编译程序段 ...
【每日一C之十七】#ifndef与#pragma once的用法与区别
每日一C之#ifndef与#pragma once
每天拾一个C语言贝壳,厚积薄发,积跬步以致千里。
今日贝壳:#ifndef与#pragma
once都用于避免同一个.h头...
#define #if #ifdef #ifndef 作用和区别
#define 用来进行定义
#define kTabBar_Height
#define kString @&哈哈哈&1212
没有更多推荐了,您好,欢迎来到365建站网-快速批量建站_企业免费建站_智能建站软件系统_在线建站和seo工具
您现在的位置:& >
> 利用DebugView++调试Windows程序的方法
利用DebugView++调试Windows程序的方法
文章来源:365jz.com &&&&点击数:169&&&&更新时间: 07:46 &&
&(287 KB)现在从运行。DebugView是一个应用程序,它允许您监视本地系统或网络上可通过TCP / IP访问的任何计算机上的调试输出。它能够显示内核模式和Win32调试输出,因此您不需要调试器来捕获应用程序或设备驱动程序生成的调试输出,也不需要修改应用程序或驱动程序以使用非标准调试输出API。正如DebugView的官方文档介绍的那样,DebugView是一个让开发者可以在自己本地的机器,或者是任意一个可以通过TCP/IP协议访问到的电脑上监视调试输出的应用程序。Debugview 可以捕获程序中由TRACE(debug版本)和OutputDebugString输出的信息。支持Debug、Release模式编译的程序(即该软件捕获的是exe直接运行时,抛出的信息,而不是Visual Studio调试时的),甚至支持内核程序,而且能够定制各种过滤条件,让你只看到关心的输出信息,而且可以定制高亮显示的内容等等,非常方便。DotNet程序的调试,是DotNet程序员必备的技能之一,开发出稳定的程序、解决程序的疑难杂症都需要很强大的调试能力。DotNet调试有很多方法和技巧。现在本文就介绍一下借助DebugView工具进行调试的方法,以及由DebugView引申出来的知识点。DebugViewDebugView是一个查看调试信息的非常棒的工具,支持Debug、Release模式编译的程序,甚至支持内核程序,而且能够定制各种过滤条件,让你只看到关心的输出信息,而且可以定制高亮显示的内容等等,非常方便。捕捉Release模式的Win32程序输出的调试信息,需要选中Capture Global Win32选项:过滤与高亮功能可以通过include、exclude设置过滤条件,包含指定字符串的输出信息将会被过滤。还可以通过exclude条件过滤掉对应进程ID的调试信息。多个条件使用“;”分隔,而且支持“*”通配符。远程调试DebugView支持远程捕捉调试信息。首先在远程机器上通过如下命令启动DebugView:DebugView.exe&/a&/t&/g&/s这样,DebugView就会以服务的方式运行,如下图:然后在本地机器上启动DebugView,并通过Connect连接到远程机器的DebugView,当远程机器中有调试信息输出时,本地就会捕获到,并展示出来:输出信息到DebugView的几种方式DebugView的一些功能是不是让你心动了呢。俗话说心动不如行动,但是在行动之前,首先要知道C#如何将调试信息输出到DebugView中。通过编程输出一些调试信息到DebugView中,一共有三种方式:Debug.WriteLineDebugger.LogKernal32.dll中的OutputDebugString方法一、Debug.WriteLine通过Debug.WriteLine可以将调试信息写入到DebugView中,如下:Debug.WriteLine(&这是调试信息&);效果如下:不过此方式只能在Debug模式下有效。具体原因下面会详细介绍。二、Debugger.LogDebug.WriteLine已经很好用了,唯一的缺点就是在Release模式下无效。那么在Release模式下就可以使用Debugger.Log方法,示例如下:Debugger.Log(0,&null,&&这是Debugger.Log输出的调试信息&);三、Kernel32.dll中的OutputDebugString方法做C++开发的应该知道可以通过OutputDebugString这个API开实现输出调试信息到DebugView中吧。那么C++能做的,C#也能做。可以通过PInvoke的方式引入此方法,这个API属于Kernel32.dll,如下声明:[DllImport(&kernel32.dll&,&CharSet=CharSet.Auto)]public&static&extern&void&OutputDebugString(string&message);然后就可以通过调用此方法,将调试信息输出到DebugView中。DebugView与日志框架比较可能有人会说,DebugView能做的事情,我用log4Net,NLog等日志框架也能做,为什么要用DebugView呢?问的好,那么我就根据平时使用DebugView的经验来给你一个用DebugView的理由:DebugView使用非常方便。相比于日志框架庞大的体系,DebugView的使用可谓是十分的简单方便。DebugView只有几百K的大小,占用空间几乎可以忽略不计。从官网下载后,直接运行exe,几乎不需要任何配置就可以正常使用。而相比于DebugView,日志框架可以算的上庞然大物。而当你从官网获得log4Net后,需要进行各种繁杂的配置。甚至你要花上几天时间专门学习一下这套框架。由此可以看出DebugView的使用实在是方便的不能再方便。DebugView是可视化工具,支持各种过滤和高亮。DebugView可以通过过滤条件来过滤不关心的信息,只显示相关的调试信息。而日志框架输出的是文件等文本信息,这些信息会包含程序运行过程中的所有信息,虽然可以通过配置文件来指定只输出哪一类信息,但是不如DebugView来的方便简单。DebugView可以实时监视。DebugView中有“自动滚动”的功能,程序中输出的调试信息,基本上瞬间就会在DebugView中展示出来,当由于大量信息导致DebugView中的文本框满了后,DebugView可以通过自动滚动滚动条,让你随时都可以看到最新的一条信息,达到类似监视的效果。而日志框架由于其写文本的特性,很难达到这种效果,即使能达到,相信也是需要对日志框架相当清楚了解,才能完成这个效果。这些理由应该足以让你使用DebugView了吧。使用DebugView的理由肯定还不止这些,如果你有更好的理由,还请分享出来。当然,DebugView与日志框架,每个都有每个的用途。通过DebugView的方式,只适合短暂的调试,而正式发布的网站或者软件,需要一套记录程序长期以来的运行状态的工具,那么就非日志框架莫属了。所以DebugView与日志框架,要在合适的地方,发挥他们最大的功效。声明Log4Net等日志框架,功能足够强大,也足够丰富,相信上面说到的DebugView的功能,也可以通过日志框架来实现。但是和DebugView比较起来,会相对复杂一些。所以上面说到的使用DebugView的理由是基于方便性的比较,DebugView有足够的方便性来让你选择使用他。ConditionalAttribute详解与条件编译说到调试,那么肯定有开发人员遇到这种情况,开发产品的时候,遇到一些问题,就在代码中加入了大量的调试输出信息,比如通过Console.WriteLine、MessageBox.Show或者通过Ilog.Log记录日志,甚至临时改变逻辑来验证逻辑的正确性等。经过这些调试信息的帮助,终于解决了产品的问题。但此时又遇到了新的问题,产品最终发布的时候,肯定是不能有这些调试信息的,可是已经加了这么多调试信息,难道要全部删除掉吗。这显然不是一个好办法,这么多代码,手一抖,很容易就删除了不相关的代码,造成不可预估的后果。做过C/C++开发的,可以从各种跨平台的开源库中看到,一堆一堆的#if....#else....#endif,这就是条件编译,这也是C/C++跨平台所依赖的最基本的东西,在Linux系统,编译这段代码,在Windows系统又编译那段代码,最终实现了代码级别的跨平台。那么C#中有没有类似的功能呢,答案当然是有,而且有两种:通过给方法加上ConditionalAttribute特性使用#if..#else..#endif,来控制代码的编译ConditionalAttribute特性下面是ConditionalAttribute的构造函数:public&ConditionalAttribute(&&&&string&conditionString
)构造函数中的参数conditionString,是一个区分大小写的条件编译符号的字符串。上面提到Debug.WriteLine时,说到这个功能只在Debug模式下才有用,Release下就不起作用了。我们从MSDN中看一下Debug.WriteLine的说明:[ConditionalAttribute(&DEBUG&)]public&static&void&WriteLine(&&&&string&message
)由此也就明白了Debug.WriteLine只能在Debug模式下使用,而在Release模式下无效的原因了。条件编译#if..#else..#endifC/C++中有#if..#else..#endif,C#中也有这些,他们都被称为预处理器。通过预定义的条件编译符号,来控制编译时编译哪部分代码。如下:public&bool&HasPermission(string&userName)
{#if&DEBUG&&&&//Debug模式下,不需要做权限判断,直接返回true
&&&&return&#else
&&&&//Release模式下,只有sa用户才有权限
&&&&if&(!string.IsNullOrEmpty(userName)&&&&userName&==&&sa&)
&&&&{&&&&&&&&return&
&&&&}&&&&else
&&&&{&&&&&&&&return&
&&&&}#endif}预定义的Debug宏在什么地方说到条件编译,是不是只有DEBUG 和 RELEASE两种情况呢,如果是这种情况的话,那也就是说DEBUG和RELEASE两种情况是定义好了的,俗话说就是“做死了”,这是作死的节奏啊。不作死就不会死,至少VS在这点上还没有作死。让我们来一步步揭开DEBUG的面纱。既然是条件编译,那么就应该和编译选项有关。我们知道C#项目,有一个属性页,可以设置很多编译的选项,如下:从图中看到,条件编译是用的DEBUG常量,或者称为DEBUG条件编译符号,是在这个编译生成选项中定义的,如果去掉这个定义,那么编译后的HasPermission方法就会根据用户名进行权限检查,程序中通过Debug.WriteLine输出的调试信息也会输出到DebugView中,也就相当于Release模式下的效果。其实DEBUG常量与Debug、Release模式并无太大的关系,唯一的关系就是,VS生成的项目中,Debug模式下,默认会选中“定义DEBUG常量”,而Release模式下,默认不会选中。也就是说,Debug模式,默认会定义DEBUG常量,而Release不会,如下图:既然DEBUG常量与Debug模式无本质上的关联,那么为什么说到Debug,就认为DEBUG呢。道理其实很简单,世上本无路,走的人多了,便成了路。本来这个DEBUG常量只是Debug模式下的默认预定义的常量,只是因为大家习惯了,并且对它的这种预定义还比较认可,时间久了,就自然而然认为DEBUG就代表Debug模式。虽然我们可以通过去掉DEBUG常量,来使条件编译在Debug模式下达到Release模式的效果,但是建议最好不要这样做,因为这就像是大家普遍都认可的一个约定,如果你一反常态,不遵守这个约定,对于程序,编译没有问题,但是后续维护肯定会相当麻烦,所以还请大侠手下留情。使用自定义的编译常量DEBUG常量作为一种普遍的约定,最好不要打破。如果有除DEBUG外的条件编译需要,可以使用自定义的编译常量。自定义编译常量有两种方法:通过编译生成属性页中的条件编译输入框,定义自己的编译常量。在代码中使用#define预处理,来定义编译常量。我们可以在条件编译的输入框中,定义自己的编译常量,多个常量之间用分号“;”隔开,而且支持中文常量,如下:当然,我们也可以在代码中通过#define预处理来定义,比如:#define&缘生梦#define&hbccdf但是有一点需要注意,define定义常量必须在using 命名空间之前,否则会造成编译错误。通过VS和Resharper改变颜色来查看哪些代码真正会被编译引入条件编译后,我们可以通过VS很快知道哪些代码会被编译:虽然条件编译的代码可以很直观的看出来,但是Conditional修饰的方法就看不出来了,这时就要借助神器Resharper了,如下图:从图中看出,release模式,由于没有定义DEBUG、缘生梦两个常量,所以,调用Test、Debug.WriteLine方法的地方就会变暗,这样很直观就知道这些代码不会被编译。再次说明一个道理,神器对于开发有很大的帮助作用。通过反编译查看生成后的代码上面总是说,有些代码会被编译,有的则不会,那么真正编译后的效果是怎样的,我们不妨使用另外一个比较强大的工具,反编译工具Reflector,来查看一下反编译后的代码:从图中的反编译后的代码可以看出,满足条件的代码会真正编译到生成的程序集里,而不满足的代码则不会生成到程序集里。Conditional修饰的方法,会有方法的实现,但是没有方法的调用。不适合在方法里做一些变量的修改。总结Conditional和条件编译Conditional为方法级别的条件编译,只能修饰方法;#if..#else..#endif为行级别的条件编译,可以指定任意代码。Conditional只能修饰无返回值的方法,而且不适合在方法中处理一些变量的值。#if..#else..#endif没有任何限制。可以通过条件编译符号输入框,或者代码中的#define定义条件编译常量,这些常量对于Conditional、#if..#else..#endif均有效。TRACE常量从上面多幅图中,可以看到,在Debug和Release模式下都会定义一个TRACE常量。现在我们知道DEBUG常量是用来控制调用Debug.WriteLine的语句是否被编译。那么TRACE常量呢。相信很多人也用过System.Diagnostics.Trace类,由DEBUG常量与Debug有关,可以想到TRACE常量与Trace有关,我们来看一下MSDN对于Trace的定义。从MSDN中,看到Trace类的定义以及可以调用的方法与Debug类似,都有WriteLine方法。下面是Trace的WriteLine方法定义:[ConditionalAttribute(&TRACE&)]public&static&void&WriteLine(&&&&string&message
)由此可以知道,TRACE常量是用来控制Trace类中WriteLine等方法是否被编译的作用。Debug类与Trace类的区别到现在为止,我们渐渐的了解了Debug类与Trace类,他们都可以通过WriteLine方法输出调试或跟踪信息,从他们的定义和暴露的方法中,可以看出他们非常相似,那么他们有什么区别呢。有些人会根据使用的效果总结为:Debug类只能在Debug模式下执行,在Release模式下无效果,而Trace类在Debug和Release模式下都可以执行。确实,在VS中新建一个项目,分别调用Debug.WriteLine和Trace.WriteLine方法,只有Trace.WriteLine输出的信息,在Release模式下有效。这也看似验证了上面的区别。但这是他们两个真正的区别吗。我们一点一点来分析。首先看这两个方法的定义:由图看到,每个方法都通过ConditionalAttribute关联了一个条件编译常量,Debug关联DEBUG常量,Trace关联TRACE常量。再来看一下这两个常量的定义:从图中看到,TRACE在Debug和Release模式下都会定义,这样在Debug和Release模式下都会执行,而DEBUG只在Debug模式下才会定义,Debug.WriteLine只在Debug模式下执行。从而也验证了上面的结论。但DEBUG与TRACE只是在默认的情况下的定义。当改变这些定义后,上面的结论就不再正确。我们来做这样的实验:Debug模式下只定义TRACE常量,Release模式只定义DEBUG常量然后在Debug和Release模式下分别执行Debug.WriteLine方法和Trace.WriteLine方法,Debug.WriteLine方法只在Release模式下有效,而Trace.WriteLine方法只在Debug模式下有效。上面的结论不再成立。为了更好的验证一下我们的结论,对他们进行反编译:由图中的反编译代码看到,除了关联的条件编译常量不同外,内部调用的方法均为TraceInternal.WriteLine,实现完全一样。那么下面来总结一下Debug与Trace的区别:Debug类关联DEBUG常量,Trace类关联TRACE常量。默认情况下,VS创建的项目Debug模式会定义DEBUG与TRACE,而Release模式只定义TRACE,使Debug只在Debug模式有效,而Trace在Debug和Release模式均有效。可以通过修改DEBUG、TRACE的默认定义,来改变Debug、Trace的默认行为。但是建议最好不要这样做,因为改变了这种默认的约定可能会出现意想不到的问题。Debug、Debugger、Kernel32的联系每个人大脑的空间都是有限的,零散的知识很容易忘掉,输出调试信息到DebugView中的三种方法,由于关联性不是很强,很容易会忘掉其中的一两种,那么既然实现相同的功能,他们之间有什么关联吗。这就要从Debug的MSDN文档说起。我们知道Debug编译的程序,运行的时候可以通过Debug.WriteLine方法输出调试i信息到DebugView,而MSDN中的解释将后跟行结束符的消息写入&Listeners&集合中的跟踪侦听器。并没有说是输出到DebugView中,而是写入到Listeners集合中的跟踪侦听器。为了弄明白原理,有必要深入的研究一下。这时就要依赖反编译工具Reflector了。从整体看上去,Debug类的每一个方法都通过Conditional与DEBUG常量管理,也就是默认情况下,Debug类的所有方法在Debug模式下均不会编译。我们再来具体看一下Debug.WriteLine方法:[Conditional(&DEBUG&),&__DynamicallyInvokable]public&static&void&WriteLine(string&message)
&&&&TraceInternal.WriteLine(message);
}再来看一下TraceInternal方法:public&static&void&WriteLine(string&message)
{&&&&foreach&(TraceListener&listener&in&Listeners)
&&&&&&&&listener.WriteLine(message);&&&&&&&&if&(AutoFlush)
&&&&&&&&&&&&listener.Flush();
}上面的代码是精简后的代码。从代码中看到会调用集合中的每一个listener的WriteLine方法。那么这些listener的WriteLine又做了什么呢:public&abstract&class&TraceListener&:&MarshalByRefObject,&IDisposable
{&&&&public&abstract&void&WriteLine(string&message);
}原来TraceListener的WriteLine是抽象类的抽象方法,那么我们得到的listener是具体类的一个抽象,相当于接口,这是微软的一贯做法,再继续下去,就需要知道是哪些具体的TraceListener了。继续上面的线索,我们是从Listeners属性中获取到的TraceListener,那么就去看Listeners的get实现:public&static&TraceListenerCollection&Listeners
&&&&&&&&InitializeSettings();&&&&&&&&if&(listeners&==&null)
&&&&&&&&{&&&&&&&&&&&&lock&(critSec)
&&&&&&&&&&&&{&&&&&&&&&&&&&&&&if&(listeners&==&null)
&&&&&&&&&&&&&&&&{
&&&&&&&&&&&&&&&&&&&&SystemDiagnostiection&systemDiagnosticsSection&=&DiagnosticsConfiguration.SystemDiagnosticsS&&&&&&&&&&&&&&&&&&&&if&(systemDiagnosticsSection&!=&null)
&&&&&&&&&&&&&&&&&&&&{&&&&&&&&&&&&&&&&&&&&&&&&//从配置文件获取listener,但是由于此处没有设置配置文件,所以先不研究这个地方
&&&&&&&&&&&&&&&&&&&&&&&&&&&&listeners&=&systemDiagnosticsSection.Trace.Listeners.GetRuntimeObject();
&&&&&&&&&&&&&&&&&&&&}&&&&&&&&&&&&&&&&&&&&else
&&&&&&&&&&&&&&&&&&&&{&&&&&&&&&&&&&&&&&&&&&&&&//这里new了一个TraceListener的集合
&&&&&&&&&&&&&&&&&&&&&&&&&&&&listeners&=&new&TraceListenerCollection();&&&&&&&&&&&&&&&&&&&&&&&&//这里我们看到了TraceListener的具体实现类DefaultTraceListener
&&&&&&&&&&&&&&&&&&&&&&&&TraceListener&listener&=&new&DefaultTraceListener&{
&&&&&&&&&&&&&&&&&&&&&&&&&&&&IndentLevel&=&indentLevel,
&&&&&&&&&&&&&&&&&&&&&&&&&&&&IndentSize&=&indentSize
&&&&&&&&&&&&&&&&&&&&&&&&};
&&&&&&&&&&&&&&&&&&&&&&&&listeners.Add(listener);
&&&&&&&&&&&&&&&&&&&&}
&&&&&&&&&&&&&&&&}
&&&&&&&&&&&&}
&&&&&&&&}&&&&&&&&return&
}从代码中,找到了具体的实现类DefaultTraceListener,那么就快点看看他的WriteLine方法吧,有点迫不及待了。实际上,WriteLine方法会调用内部的Write方法:private&void&Write(string&message,&bool&useLogFile)
{&&&&if&(base.NeedIndent)
&&&&{&&&&&&&&&//写缩进,实际是空格
&&&&&&&&&&this.WriteIndent();
&&&&}&&&&if&((message&==&null)&||&(message.Length&&=&16384))
&&&&{&&&&&&&&&//输出消息
&&&&&&&&&&this.internalWrite(message);
&&&&}&&&&else
&&&&{&&&&&&&&//当消息很长时,会通过internalWrite方法将消息多次输出
&&&&&&&&&int&startIndex&=&0;&&&&&&&&while&(startIndex&&&(message.Length&-&16384))
&&&&&&&&{&&&&&&&&&&&&this.internalWrite(message.Substring(startIndex,&16384));
&&&&&&&&&&&&startIndex&+=&16384;
&&&&&&&&}&&&&&&&&this.internalWrite(message.Substring(startIndex));
&&&&}&&&&if&(useLogFile&&&&(this.LogFileName.Length&!=&0))
&&&&{&&&&&&&//输出到日志文件中
&&&&&&&&this.WriteToLogFile(message,&false);
}与输出信息有关的有两个地方,一个是调用internalWrite,另外一个是WriteToLogFile。从WriteToLogFile是有执行条件的。感兴趣的可以研究一下。重点来看一下internalWrite方法。private&void&internalWrite(string&message)
{&&&&if&(Debugger.IsLogging())
&&&&{&&&&&&&//调用Debugger.Log方法,这个方法可以输出信息到DebugView中
&&&&&&&&Debugger.Log(0,&null,&message);
&&&&}&&&&else&if&(message&==&null)
&&&&&&&&SafeNativeMethods.OutputDebugString(string.Empty);
&&&&}&&&&else
&&&&{&&&&&&&//调用Native方法&&&&&&&&SafeNativeMethods.OutputDebugString(message);
}internalWrite中调用了两个比较重要的方法。其中Debugger.Log方法是不是很熟悉呢。我们刚刚在上面总结了三种输出调试信息到DebugView的方法,其中就包含了Debugger.Log,而Debug.WriteLine方法中,又会调用到Debugger.Log方法,这样,这两个方法就建立起了联系。再来看SafeNativeMethods.OutputDebugString,看到这个类的命名,以及对Win32API的了解,就能想到,这肯定是通过PInvoke等方法对Win32API的封装,看其定义:[DllImport(&kernel32.dll&,&CharSet=CharSet.Auto)]public&static&extern&void&OutputDebugString(string&message);果然,这就是对kernel32.dll中的OutputDebugString的封装调用,而这又是上面三种方法其中的一种。好了,这样Debug、Debugger、OutputDebugString就全都联系到了一起,他们之间有了联系,是不是就更容易记忆了。配置TraceListener从上面对Debug.WriteLine的一步步跟踪分析的过程中,我们看到了对于TraceListener的获取,一种方式是DefaultTraceListener,另外一种就是如下:SystemDiagnosticsSection&systemDiagnosticsSection&=&DiagnosticsConfiguration.SystemDiagnosticsSif&(systemDiagnosticsSection&!=&null)
{&&&&&//从配置文件获取listener,但是由于此处没有设置配置文件,所以先不研究这个地方
&&&&listeners&=&systemDiagnosticsSection.Trace.Listeners.GetRuntimeObject();
}这几行代码就是从配置文件的system.diagnostics中获取TraceListener。关于配置文件具体的读取和解析过程,本文就不再详细介绍了,感兴趣的朋友可以自行研究,或者等到我的后面博文详细介绍。那么现在主要说一下如何通过配置文件来设置TraceListener,如下:&configuration&
&&&&system.diagnostics&
&&&&&&&trace&autoflush=&true&&indentsize=&2&&
&&&&&&&&&&listeners&
&&&&&&&&&&&&&add&name=&myListener&&type=&System.Diagnostics.ConsoleTraceListener&&/&
&&&&&&&&&&/listeners&
&&&&&&&/trace&
&&&&/system.diagnostics&&/configuration&同样,有配置文件,那么就可以通过代码来实现同样的功能,如下:Debug.Listeners.Add(new&ConsoleTraceListener());
Debug.AutoFlush&=&
Debug.WriteLine(&这是Debug.WriteLine输出的调试信息&);Debug编译与Release编译的区别Debug与Release的区别,这个问题,相信很多人都会有疑问,也会有很多人有自己的答案,我听到过的答案有这些:Release比Debug运行速度快,执行效率高。Debug 是调试用的,可以打断点执行。Release是发布用的,不能打断点执行。Debug编译的文件大,Release生成的程序集小。Debug会生成pdb文件,Release不生成pdb文件。这些答案看上去好像都对,但是为什么Debug与Release有这么大的区别呢,这就需要深入的思考一下。在Debug类与Trace类的区别一节中,相信有些朋友已经明白,Debug编译与Release编译的区别其实是编译配置的不同,DEBUG、TRACE常量的定义就是其中不同的地方。那么Debug编译与Release编译还有什么不同呢。针对这个问题,我总结了一下,主要区别有下面几点:常量定义不同优化代码的不同包含的调试信息不同输出路径不同接下来,我们详细的看一下。常量定义不同这个相信大家已经非常清楚了,Debug模式下会定义DEBUG、TRACE常量,而Release模式下只定义TRACE常量,如下图所示优化代码不同Debug模式下,默认不会进行代码的优化,而Release模式下,由于默认选中了“优化代码”选项,所以编译器会对生成的代码进行优化,以提高运行速度。包含的调试信息不同编译生成的属性页中有一个“高级”按钮,点击后会弹出一个对话框,然后可以对编译生成进行一些设置,如下Debug与Release的高级选项对比:从图中看到,Debug模式下默认会生成全部的调试信息,而Release模式下只生成pdb文件。输出路径不同这一点详细大家都很清楚了,Debug模式下会输出到Debug目录,Release模式下会输出到Release目录,如图:Debug编译与Release编译的区别总结说了这么多,我们再来思考本节开始时说到的关于Debug编译与Release编译的区别的答案,可以得出这样的结论:Release比Debug运行速度快,执行效率高。由于Release模式编译会对生成的代码进行优化,所以会使生成的程序集在运行的时候比Debug编译的程序集运行速度快。Debug 是调试用的,可以打断点执行。Release是发布用的,不能打断点执行。由于Release模式对代码进行优化,生成的调试信息只包含pdb文件,所以导致调试起来会比较困难。Debug编译的文件大,Release生成的程序集小。依然是由于Release模式对生成的代码进行了优化,所以就导致生成的程序集相对来说比较小。Debug会生成pdb文件,Release不生成pdb文件。这个要看VS的默认选项,在2012中,Release模式默认会生成pdb文件的,其他版本的VS可能会有不同的情况。知道这些区别后,我们就可以通过修改编译配置来使Debug程序达到Release的效果,使Release程序达到Debug的效果。当然,还是那句话,虽然可以实现这样的效果,但是建议绝对不要这样做,不然程序维护起来,肯定会遇到很多问题。另外,可以使用DebugView++ 替换:&
如对本文有疑问,请提交到交流论坛,广大热心网友会为你解答!!
您可能感兴趣的文章:
if(f.msg.value.length 500)
alert("你的评论是不是太长了?请填写500字以内的评论。");
$("#commetcontentNew").html(waithtml);
url:'/plus/comment.php?dopost=send&aid=24525&time='+Number(new Date()),
type: 'POST',
data:{msg:f.msg.value,username:f.username.value,validate:f.validate.value},
success:function(d){
$("#commetcontentNew").html(d);
(169人查看,0条评论)
------分隔线----------------------------
大家感兴趣的内容
最近更新的内容
手机客户端

我要回帖

更多关于 if endif 的文章

 

随机推荐