⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 delphi_compile.txt

📁 很少见的DELPHI的编译指令说明文档
💻 TXT
📖 第 1 页 / 共 3 页
字号:
ShowMessage(''Q 也变成开启状态了''); 
{$ENDIF} 
ShowMessage() 与 {$Q+}会在$R+ 的情形下才编译, 因此, 虽然我们事前特别指 示为{$Q-}, 第二个的ShowMessage()在程序执行时也可以看到「Q 也变成开启状 态了」。 
{$IMAGEBASE 档案基础地址} 

    这个Compiler directive用来指示.EXE或.DLL加载时的预设地址。例如: {$IMAGEBASE $00400000}。如果指定加载的地址空间之前已经有其它模块占用了, Windows会为.EXE重新配置一个新的加载地址。对于.DLL来说, 如果可以成功配置到我们写在{$IMAGEBASE}的地址, 由于不需要重新配置内存地址, 不仅加载的速度 较快, 如果有其它程序也参照到这个DLL的话, 也可以减少加载时间与内存的消 耗。 

使用这个Compiler directive时需要注意的事项有: 

指定的叙述必须是一个大于$00010000的32位整数数值, 同时, 较低位置的16个位必须是零。 
DLL的建议地址范围从$40000000到$7FFFFFFF, 该范围的地址可以同时适用于Windows 95与Windows NT。 
{$I文件名称} 含入档案 

    以Delphi IDE修改Compiler directives的确相当方便, 但往往我们仍然需要将Compiler directives直接加入程序中, 可是当我们这样作之后不用多久, 就会发 现要一一重新修改各个单元中的这些Compiler directives时, 实在是既无聊而又 容易出错的工作。这时候, 假如您一开始就采用{$I文件名称}, 整件事就会变得很简单。怎么做呢? 让我用一个例子告诉您 -- 

先用一般的文书编辑器建好一个MySet.inc的普通文本文件, 内容为: 
{$H+} 
{$DEFINE _Proversion} 

在我们的程序中, 加入一列{$I MySet.inc}, 例如: 
unit Unit1; 
{$I MySet.inc} 

interface 

implementation 
 
{$R *.DFM} 
 
procedure TForm1.Button1Click(Sender: TObject); 
begin 
{$IFDEF _ProVersion} 
ShowMessage(''专业版''); 
{$Else} 
ShowMessage(''只有专业版才有此功能''); 
{$ENDIF} 
end; 
    这是子程序的观念嘛! 没错, 就是这么简单而已, 以后如果有任何变化, 修改MySet.INC, 然后Project/Buile All即可, 实在是够简单的了。 

    基本动作会了之后, 让我告诉你多一点有关{$I文件名称}的事。 

一旦应用了{$I文件名称}, 几乎等于Compiler在编译时, 让Compiler将这个档 案的内容贴进我们的程序中的那个位置。 
如果没有注明扩展名, Delphi预设这个档案是.PAS。 
如果在项目的目录中找不到这个档案的话, Delphi会陆续搜寻Tools/Options/Library中的Library Path中的目录。 
    另外, 当您写作了一个DLL, 使用者在使用其中的函数前必须宣告过, 如果能够一并提供这些函数的宣告文件, 使用者只要一行{$I xxx}即可, 是不是很方便呢? 

{$I+} EInOutError检查 

    在{$I+}(系统默认值)状态编译的程序, 一旦发生I/O错误时, 将会举发一个EInOutError的例外, 假如我们在特定的情况下不希望出现这个例外的讯息时(例如前文提到的侦测档案是否存在函数), 可以将这个Compiler directive设为{$I-}, 此时, 程序执行时是否发生过错误,程序设定师必须自行检查IOResult这个公用变 数的值, 如果是零, 表示没有错误, 非零的错误代码含意请详查Online help。 

{$L文件名称} 连结目标文件 

    如果您有一个.OBJ文件要并入Delphi的程序时, 可以在程序中加入: 

{$L OTHER.OBJ} 

    这样, 就可以使用OTHER.OBJ中的程序了, 值得注意的是, 函数或程序在呼叫前,仍然必须用external宣告过, 表明这些模块是来自「外部」的函式。 

    举例来说, 笔者有一份由Keypro厂商提供的.OBJ档, 在使用时, 相关的程序如下: 

{$L hasptpw.obj} 
{$F+} 
procedure hasp (Service, SeedCode, LptNum, Pass1, Pass2 : word; 
var p1,p2,p3,p4 : word); external; 
{$F-} 

    经过{$L hasptpw.obj}宣告之后, 程序的其它部分就可以直接呼叫原先位于 hasptpw.obj中的hsap这个程序了。 

{$L+} 区域符号信息 

    在{$L+}时, Delphi会额外加入一些区域符号信息, 这使得我们可以应用Delphi IDE中的View/Call Stack, View/Watch在程序执行时检视变量内容与函式呼叫的 关系。 

    应用这个Compiler directive的注意事项有: 

{$D-}时, {$L+}不会有作用。 
使用{$L+}, 只会加大.DCU的档案大小, 对.EXE的大小与执行速度并没有影响。 
{$H+} 长字符串宣告 

    Delphi 2.0之后, 字符串多了一个更为好用的长字符串, 不仅没有数据长度255的限制与C语言惯用的Null-terminated string兼容性也大为提高。 

使用{$H}时的注意事项有: 

{$H+}的编译情形下, 以string定义的字符串变量都是长字符串, 请注意, 字符串是否为长字符串是在字符串定义时决定的, 例如: 
procedure TForm1.Button1Click(Sender: TObject); 
{$H-} 
var 
s: string; 
begin 
{$H+} 
s := ''测试一下长字符串''; 
Windows.MessageBox(0, pchar(s), ''讯息'', 64); 
end; 

    由于var前{$H-}的缘故, 虽然在begin后我们立即设定为{$H+}, 但s仍然是一个短 字符串, 所以, 自然不能像是长字符串一样, 以pchar强制型别转换后当作Null-terminated字符串使用。 

承上, 不管程序是{$H+}或{$H-}, 只要字符串是以长字符串方式定义的, 即使begin..end;中改成{$H-}, 该字符串的操作仍然具有长字符串的特性。 
    因此, 由于VCL中的字符串都是长字符串, 即使我们的程序是{$H-}, 仍然可以拿它们 当长字符串来使用。 

不论{$H}的状态如何, 以AnsiString定义的一定是长字符串; 以string[n]或ShortString定义的一定是短字符串。 
{$M 16386, 1048576} 内存配置大小 

    要改变唯迭(Stack)内存配置大小时, 我们可以有以下两种选择: 

使用{$MINSTACKSIZE数字}, {$MAXSTACKSIZE数字}, 分别指定最小.最大的Stack大小. 
或者使用{$M min, max}, 同时指定最小与最大的值。 
    使用这些Compiler directive时的注意事项有: 

写在.DPR中才有效果。 
堆栈的最小数字必须介于1024至21474835647之间。 
堆栈的最大数字必须介于$MINSTACKSIZE至21474835647之间。 
当内存不足而无法满足最小的堆栈大小时, Windows会在启动这程序时提出错 误报告。 
当程序要求的内存超过$MINSTACKSIZE的大小时, 将举发EStackOverflow例外 。 
{$Z1} 最小列举大小 

    这个Compiler directive将影响储存列举型态时最小所需的byte数值。如果宣告 列举型态时, 数值不大于256, 而且也在系统预设的{$Z1}时, 这个列举型态只占 用一个byte储存的。{$Z2}时, 以两个byte储存, {$Z4}时, 以四个byte储存。因 为C语言通常以WORD或DWORD储存列举型态, 如果您的程序需要与C、C++沟通时,{$Z2}{$Z4}就很管用了 

{$Z+}, 与{$Z-}分别对应到{$Z1}和{$Z4}。 

{$P+} 开放字符串参数 

    在程序与函数宣告时, 其中的字符串自变量, 在{$P+}时表示是Open string; {$P-}时 , 只是一般的字符串变量而已。这个Compiler directive只在{$H-}时有作用。 

{$O+} 最佳化开关 

    建议您维持{$O+}的系统默认值。开启这个Compiler directive, Delphi会自动进行最佳化处理, 程序可以因此跑得快一些, 您可以放心的打开这个编译开关, Delphi不会进行不安全的最佳化而使您的程序执行时发生错误。 

{$Q-} 满溢检查, {$R-} 范围检查 

    {$Q}与{$R}是一组搭配使用的Compiler directive, 它们将检查数值或数组的操作是否在安全的边界中, {$Q}会检查整数运算(如+, -, Abs, Sqr, Pred, Succ等 ), 而{$R}则检查字符串与数组的存取是否超出合理边界范围等问题。

    使用这两个Compiler directives会因为这些检查动作而降低程序执行的速度, 通 常我们会在除错时开启这两个编译开关。 

{$U-} Pentium CPU浮点运算安全检查 

    还记得早期Pentium CPU浮点运算不正确的事吧? 这批CPU应该回收得差不多了, 但如果您仍然不确定程序会不会意外的遇到漏网之鱼或黑心牌经销商的话, 请将 这个Compiler directives设为{$U+}。 

    根据Borland手册的说明, 如果CPU是没有暇疵的, 设定{$U+}对于执行速度只有轻 微的影响; 但如果是问题CPU, 浮点的除法速度会因此慢上三倍, 是否要打开这个 开关, 您心中应该已有取舍。 

{$R文件名称} 资源档 

    在您还没有开始学习Compiler directives之前, 这个指令就已经出现在您的程序中了,-次开出一个新的form时, Delphi自动在Implement开头部分中加入{$R *.DFM}, 在Project/Source中看到的.DPR程序中也有{$R *.RES}, 这些是什么意思呢? 意思是说, 在编译连结时, 含入与项目主档名同名的.RES, 以及与form unit档案同名的.DFM等资源档。 

    如果您需要在程序中使用额外的资源(例如: 自订鼠标指针), 请注意不要自行以Resouse WorkShop或Image Editor等资源编辑器更改这些与Project或Form同名的 资源档, 改变这些同名的档案不仅无效, 可能还有不可预期的错误。因些, 您应 该在另外一个资源档中存放这些资源, 并于{$R}中写明档案的名称将其连结进来, 例如: 

{$R MyCursor.res} 

{$T-} @指针型态检查 

    应用@操作数可以取得变量的地址, 在{$T-}时, 以@取得是一个无型别的指标(Pointer)。反过来说, 在{$T+}时, 是有型别的指标, 假定I是一个integer的变量,@I所得到的即是相当于^Integer(Pointer of Integer)的指标。 

{$WARNINGS ON} 编译器警告 

    这个Compiler directive与{$HINTS}的作用类似, 同样会对程序的可能问题提出 警告。不同的是, 在{$WARNINGS ON}时, Compiler会对未初始化的变数、没有传 回值的函数、建构抽象对象等情况提出警告。 

{$J-} 型态常数只读 

    从前笔者曾经对以下的程序产生过疑惑: 

{$J+} 
procedure TForm1.Button1Click(Sender: TObject); 
const 
VarConst: integer = 4; 
begin 
VarConst := 5; 
ShowMessage(IntToStr(VarConst)); 
end; 

    const不是常数吗? 为什么可以改呢? 在先前的Pascal版本中, 以const VarName: DataType = const value; 定义的具型态常数的确是可以改的, 假如您希望常数就是常数, 它不应该允许修改, 请将这个Compiler directive设为{$J-} 不论是{$J+}或{$J-}, 以const VarName = const value; 定义的常数(没有加上 型别宣告), 是一个真正的常数, 其它的程序不可以改变其内容。 

    其实{$J+}时还有一个妙用, 那就是宣告出类似C语言static的变量, 换句话说, 产生了一个与Application相同生命周期的变量。在这种情形下, 变量只在第一次 使用时才会建立, 函数或程序结束时, 该变量也不会消灭, 下一次再呼叫到这个 函数或程序时, 我们仍然可以参考到上次执行结束时的值。让我们试一下这个例子: 

{$J+} 
procedure TForm1.Button1Click(Sender: TObject); 
const 
i: integer = 0; 
begin 
ShowMessage(IntToStr(i)); 
Inc(i); 
ShowMessage(IntToStr(i)); 
end; 

    第一次执行时, 我们分别会看到「0」「1」, 再点一次这个按钮时, 看到的将是 「1」「2」。 
 

返回

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -