注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

Mr.Right

不顾一切的去想,于是我们有了梦想。脚踏实地的去做,于是梦想成了现实。

 
 
 

日志

 
 
关于我

人生一年又一年,只要每年都有所积累,有所成长,都有那么一次自己认为满意的花开时刻就好。即使一时不顺,也要敞开胸怀。生命的荣枯并不是简单的重复,一时的得失不是成败的尺度。花开不是荣耀,而是一个美丽的结束,花谢也不是耻辱,而是一个低调的开始。

网易考拉推荐

Delphi预编译指令  

2013-01-24 17:57:00|  分类: 编程 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

Delphi作为一个优秀的开发工具,这不仅是由于它开创了"构件(Component)"时代,影响深远;另一个原因是它拥有非常出色的编译器,Borland(Inprise)公司宣称Delphi具有世界上最快的编译器,如果你使用过Visual C++和Delphi你会明显体会到这一点。Delphi快速高效的编译器主要来自Object Pascal的严谨,使用Delphi随时都在和编译器交流,大部份情况下不需要我们干涉编译器的运行,但是有时也需要对编译器进行必要的设置。对于普通的程序,Delphi是不需要编程者去添加编译器指令的,Delphi已经自动完成,但是要得到高品质的应用程序或者有特殊的要求的程序就必须熟悉Delphi的编译指令。使用编译选项的好处有:

1.协助除错:经常会在开发应用系统的过程中﹐特别加入一些除错程序或者回馈验算的程序﹐这些除错程序对于软体品质的提升有极其正面的功能。然而开发完成的正式版本中如果不需要这些额外的程序的话﹐要想在一堆程序中找出哪些是除错用的程序并加以删除或设定为注解﹐不仅累人﹐而且容易出错﹐况且日后维护时这些除错程序还用得着。此时如果能够应用像是$IFDEF的Compiler Directives ﹐就可以轻易的指示Delphi要/不要将某一段程序编进执行档中。同时﹐Compiler本身也提供了一些错误检查的开关﹐可以预先对程序中可能的问题提醒程序设计师注意﹐同样有助于撰写正确的程序。

2.版本分类: 对于像是「试用版」「普及版」「专业版」的版本分类﹐也可以经由Compiler Directive的使用﹐为最后的产品设定不同的使用权限。其他诸如「中文版」「日文版」「国际标准版」等全球版本管理方面﹐同样也可以视需要指示Delphi特别连结哪些资源档或者是采用哪些适当的程序。

{$IFDEF WIN32}

{$R XXX32.DCR}

{$ELSE}

{$R XXXX16.DCR}

{$EDNIF}

3.程序的重用与管理:透过像是{$I xxxx} 这样的Compiler Directives﹐我们也可以适当的含入某些程序, 同样有助于切割组合我??们的程序或编译设定。

4.设定统一的执行环境: 单元或程序可能会在不同的机器上编译, 直接将Compiler directives加入程序, 不仅可以免去程序使用前需要特别更改IDE的麻烦, 更重要的是解决了各个单元间要求不同编译环境的歧异。

使用编译设置对话框

编译器的编译指令是用于指定编译器对项目编译过程的动作和行为。可以通过[Project]->[Options]->[Complier]选项页进行设置,绝大部分的编译环境都可以通过这一对话框进行调整,他包含了对代码、语法、调试信息等的设置。

1.代码设置(Code Generation)

Optimization: 代码优化开关

Aligned record fields: 字对齐数据。这个编译指令能够在变量和类型化常量的字节对齐和字对齐之间进行切换,其作用是全局的。

Stack frames: Windows 堆栈帧。其作用域是局部的,他使编译器成为远端过程和函数生成特定的开头和结尾代码。这个指令用于Windows 3.0的实模式,对所有Delphi应用程序他应该是关闭的。

Pentium-safe FDIV: Pentium安全FDIV检查。此指令能够在Pentium处理器中指定编译器是否创建能够检测和使用有缺陷的浮点除法指令的代码。

2.运行期错误(Runtime Errors)

Range Checking: 范围检查。这个指令的作用范围是局部的,用于控制范围检验代码的生成。

I/O Checking: I/O检查。这个指令的作用域为局部,用来生成对一个文件的输入和输出过程和调用结果进行检查的代码。一般应该使其功能打开。

Overflos Checking: 溢出检查。其作用是生成对算术溢出检查的代码。

3.语法设置(Syntax Optings)

Strict Var- strings: 静态变量串开关。用来控制对以变量参数形式传递的串的类型检查。

Comlete Boolean Eval: 完全布尔表达量判定。用于执行强制的完整表达式判定。完全布尔量判定,有可能导致系统崩溃,所以一般不使用他。

Extended Syntax: 扩展语法开关。他能允许或禁止Delphi的扩展语法。

Typed @ Operator: 类型化的@运算符检查。应用于局部的变量引用上,控制@运算符返回的指针值类型。

Open Parameters: 开放参数开关。用于控制使用String关键字声明的变量参数。开放参数允许将大小不一的串变量传递到同一个过程或函数中,一般在汇编中会使用到。

Huge Strings: 字符串类型开关。用于控制Ansistring和Shortstring类型的切换。当打开时符合Ansistring,关闭时符合Shortstring。

Assignable Typed Constants: 可分配类型常量。用于向下与Delphi 1.0兼容。

4.调试(Debugging)

Debug Information: 调试信息开关。用于设置是否把调试信息写入以编译的单元文件(.dcu)。

Local Symbols: 局部符号开关。允许或禁止局部符号信息的创建。

Reference Info/Definitions Only: 符号信息开关。用于允许或禁止由Delohi的对象浏览器使用的符号引用信息的生成。

Assertions: 用于控制局部代码的属性。

Use Debug DCUs: 使用或禁止VCL的DCU文件调试。

5.信息(Messages)

Show Hints: 显示暗示。

Show Warnings: 显示警告。

使用编译指令(Compiler directives)

除了使用编译设置对话框对编译器进行设置外,还可以通过编译指令来对编译器进行设置。对于局部的编译器设置,只有使用编译指令来完成。对于开关编译指令,通过在编译指令后加入指示开关状态的加号和减号来控制编译器。例如:{$B+} : 打开完全布尔量检查。 {$Q-} : 关闭溢出检查。通常,编译指令的作用域是在编译指令后的代码部分,而对于全程的编译指令应该防在单元接口部分的开头。 编译设置对话框的设置都有与之对应的编译指令用于在代码中对编译器进行设置,如下所示。

设置项 编译指令

Optimizations {$O}

Aligned record fields {$A}

Stack frames {$W}

Pentium-safe FDIV {$U}

Range Checking {$R}

I/O Checking {$I}

用$I编译指令将inc文件包含进来,inc文件中的内容就象源代码一样,可以执行。{$I XXXX.INC}

Overflow Checking {$Q}

Strict Var-strings {$V}

Comlete Boolean Eval {$B}

Extended Syntax {$X}

Typed @ Operator {$T}

Open Parameters {$P}

Huge Strings {$H}

Assertions typed constants {$J}

Debug information {$D}

Local sysnbols {$L}

在这些编译指令以外还有一些非常有用的编译指令。

$R Filename : 这个编译指令是最为常用的编译指令,他是资源文件编译指令,用于指定连接到执行文件和库的资源文件,例如在工程文件(.dpr)中会有{$R *.RES}的编译指令,表明把后缀为 .RES的与工程文件同名的资源文件连接入执行文件,也可以指定一个资源文件,资源文件的使用对于编写Windows程序来说是很重要的基础。

$I Filename :这个编译指令功能类似于C语言的#Include , 用于指定编译时包括的文件。

Delphi的注释结构:{ 括在此大括号中的内容为注释内容 ,此内容可以为多行,只要在两个大括号之间即可以,注释掉的内容一般都会以特殊的字体和颜色显示(适合所有的注释类型),很容易区分};(* 在此括号和星号之间的内容为注释内容 *);// 在此双反斜线后的内容为注释内容,此处只能为一行。注释不能被嵌套。如{{}}将不起作用,但是(*{}*)是允许的。

还有一种注释它跟普通的注释很像,但它有特殊的一点 以 "{$" 开始,以"}",此种注释称为编译指令。如{$WARNINGS OFF},它将告诉编译器不要产生错误警告信息。编译指令不是一种注释,而是一种告诉编译器如何编译的指示符。

一个编译指令实际上是一个标志符(编译器所能识别的标志符),且有其固定的语法。编译器根据不同的指令按不同的方式编译程序。你可以将一个编译指令放在程序的任何位置(有些不应写在Unit中,对于像是{$MINSTACKSIZE}{$MAXSTACKSIZE}管理堆叠大小, 或者像是{$APPTYE}指示程序编译成图形/文字模式的Compiler directives, 只能写在.DPR中, 写在Unit中是没有效果的。)。编译指令的开始字符 " $" ,它总是出现在 "{"符号之后,$之后为编译指令的实际部分,可以是一个或多个字符(根据指令的不同而定),在指令后还可以包含一个或多个需要的参数。一个编译指令的结束符为"}"。

Delphi编译指令共有三种,开关编译指令、参数编译指令和条件编译指令,下面分别讲述三种编译指令

开关编译指令地特点是它有 on 、off 两种转换状态。对于单字符版本,你可以在编译指令后添加 "+"或"-"。对于长字符版本,你可以在编译指令后添加 "on"或"off"。开关编译指令又分为全局和局部两种。全局编译指令影响全部的编译内容,它必须在放在程序和单元声明之前。局部编译指令仅影响局部的编译内容,它的影响范围是,直至下一个最近的编译指令。它可以放在程序的任意位置。开关编译指令可以组合成一个简单的编译指令组,中间用逗号分开,但不能有空格。例如:{$B+,R-,S-}

参数编译指令通过参数指定影响的的内容,参数可以为文件名或内存大小等。条件编译指令指定的条件如何编译特定的区域段。也就是如果满足某个条件,则按照一种方式编译,否则按另一种方式编译。所有的编译指令(除开关编译指令外)在名字和参数之间至少应有一个空格。例如:

{$B+}

{$DEFINE Debug}

{$IFDEF Debug}

{$ENDIF}

条件编译的嵌套最多可以16层:在使用{$IFDEF}…{$ENDIF}条件编译我们的程序时, 一个{$IFDEF}中可以再包含另一个{$IFDEF}, 但深度最多只能16层, 虽然是个限制, 但以正常的情形来说, 这应该已经足够了。

条件编译指令是非常重要的编译指令,他控制着在不同条件下(例如,不同的操作系统)产生不同的代码。条件编译指令是包含在

注释括号之内的,如下表所示。

条件编译指令 含义

$DEFINE 用于定义一个条件符号,一旦定义,条件符号就为真

$ELSE 与$IFDEF配合使用,如果$IFDEF条件为假,则只对源文件$ELSE后一小部分进行编译

$ENDIF 结束一个以$IF开始的条件段

$IFDEF 对条件符号进行判断,为真则编译源文件

$IFNDEF 对条件符号进行判断,为假则编译源文件

$IFOPT 根据编译开关状态,对源文件编译

$UNDEF 撤消以前的条件符号定义

这些条件编译指令是非常有用的。例如,可以通过开关的状态来控制编译:

{IFOPT R+}

showmessage('Compiled with range-checking');

{$ENDIF}

也可以通过定义条件符号来控制编译:

{$Define s}

……

{$ifdef s}

showmessage('yes');

{$else}

showmessage('no');

{$endif}

他的编译结果是显示'yes',但是如果省去{$Define s}则显示'no'。

在Delphi中已经预定义了一些关键的条件符号,如下表所示。

条件符号 含义

VERxx 编译器版本,XX表示版本,例如:Delphi 1.0 的编译器版本为80、Delphi 5.0 的编译器版本为130

WIN32 是否WIN32的运行环境(Windows 95.98/NT/2000)

CPU386 是否Intel386以上的处理器

CONSOLE 是否控制台程序



-----------------------------------------------------------

The $I compiler directive covers two purposes. Firstly to include a file of code into the current unit. Secondly, to control whether exceptions are thrown when an IO error occurs.
 
Version 1
 
This is very useful for including compiler directives or common code into all of your units to ensure consistency, and a single point of control.
 
The default file name extension is .pas, so for .pas files, only the name is required. Use quotes if the name includes one or more spaces.
 
For example:
 
Common.pas file:
{$ReferenceInfo On}
{$RangeChecks On}
{$OverFlowChecks On}

Unit1.pas file:
...
{$I Common}
...

 
Versions 2 and 3
 
{$I+} default generates the EInOutError exception when an IO error occurs.
 
{$I-} does not generate an exception. Instead, it is the responsiblity of the program to check the IO operation by using the IOResult routine.
Notes
$I FileName is equivalent to $Include FileName.
$I- is equivalent to $IOChecks Off.
$I+ is equivalent to $IOChecks On.

This directive can be used multiple times within your code.




function IOResult : Integer;
Description
The IOResult function retrieves the result of the last I/O (file input/output) operation.
 
This number is zero if the operation succeeded, or a positive number if it failed.
 
Use IOResult when you have disabled the default Delphi IO error trapping. When $IOChecks is On, Delphi raises exceptions for the errors. When Off, Delphi does not raise exceptions, requiring the code to inspect IOResult.
Notes
Warning : retrieval of the IO result is a one-off activity - the retrieval resets the value to 0.




Example code : Trapping IO exceptions, and using IOResult
// Full Unit code.
// -----------------------------------------------------------
// You must store this code in a unit called Unit1 with a form
// called Form1 that has an OnCreate event called FormCreate.
 
unit Unit1;
 
interface
 
uses
  SysUtils,
  Forms, Dialogs;
 
type
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
  end;
 
var
  
Form1: TForm1;
 
implementation
{$R *.dfm} // Include form definitions
 
procedure TForm1.FormCreate(Sender: TObject);

var
  error : Integer;

begin
  // Try to create a new subdirectory in the current directory
  // Switch off I/O error checking
  {$I-}
  MkDir('TempDirectory');

  // Did the directory get created OK?
  error := IOResult;
  if error = 0
  then ShowMessage('Directory created OK')
  else ShowMessageFmt('Directory creation failed with error %d',[error]);

  // Try to create the directory again - this will fail!
  MkDir('TempDirectory');
  error := IOResult;
  if error = 0
  then ShowMessage('Directory created OK again')
  else ShowMessageFmt('Repeat creation failed with error %d',[error]);

  // Delete the directory to tidy up
  RmDir('TempDirectory');

  // Switch IO checking back on
  {$I+}
end;
 
end.
  评论这张
 
阅读(754)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2016