Delphi 的编译指令(1): $DEFINE、$UNDEF、$IFDEF、$ELSE、$ENDIF

本文详细介绍了Delphi中的条件编译技术,包括如何判断操作系统、自定义条件标识符、取消定义标识符等内容,并提供了多个实用示例。此外,文章还讲解了调试编译指令时的注意事项、编译指令的位置及条件标识符的有效范围。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一个程序从无到有的过程是这样的: 编辑代码 -> 预处理 -> 编译(dcu) -> 链接(exe).

什么是预处理?
譬如 VCL 中有很多代码是兼容 Linux , Windows 下就需要在编译之前预处理掉那些 for Linux 的代码.



1、判断操作系统:


其中的 "MSWINDOWS" "LINUX" 就是 Delphi 预定义的 "条件标识符".


begin

  {$IFDEF MSWINDOWS}

    ShowMessage('Windows');

  {$ENDIF}

 

  {$IFDEF LINUX}

    ShowMessage('Linux');

  {$ENDIF}

end;



2、自定义条件标识符(DEFINE):


下面例子中自定义了条件标识符: WanYi; 标识符和定义它的指令都不区分大小写, 但大家一般惯用大写.


begin

  {$DEFINE WANYI}

  {$IFDEF WanYi}

    ShowMessage('标识符 WanYi 已定义');

  {$ELSE}

    ShowMessage('标识符 WanYi 未定义');

  {$ENDIF}

end;



3、取消条件标识符的定义(UNDEF):


begin

  {$DEFINE WANYI}

  {$IFDEF WANYI}

    ShowMessage('确认标识符 WanYi 是否定义');

  {$ENDIF}

 

  {$UNDEF WANYI}

  {$IFDEF WANYI}

    ShowMessage('再次确认标识符 WanYi 是否定义');

  {$ENDIF}

end;



4、取消定义的简单办法:


{$...} $ 前面随便加点什么, 让它变成 "注释", 譬如: {.$}


begin

  {.$DEFINE WANYI}

  {$IFDEF WANYI}

    ShowMessage('确认标识符 WanYi 是否定义');

  {$ENDIF}

 

  {.$UNDEF WANYI}

  {$IFDEF WANYI}

    ShowMessage('再次确认标识符 WanYi 是否定义');

  {$ENDIF}

end;



5、调试编译指令时特别要注意的:


Delphi 有个常识: 如果单元代码没有改变, 相应的 dcu 不会重新生成!

因此, 为了有准确的调试结果, 执行前先用 Shift+F9 强制编译当前工程, 然后再 Run;
强制编译所有相关单元也可以, 方法: Project -> Build all project.

当然修改下代码也很方便, 譬如在代码中打个空格再退回来.



6、测试预定义的 Debug Release:


当我们当新建一个工程, Delphi 默认的是调试(Debug)状态, 当我们发布软件时应该切换到发布(Release)状态.
两种状态下编译指令是有区别的, Release 状态下发布的 dcu exe 会更小、更优化.

Debug
Release 的切换方法:
进入 Project Manager -> Build Configurations, Debug Release 上双击, 或从右键 Activate.

下面的代码可以检测到这种改变, 不过要注意上面提到的 Shift+F9 Project -> Build all project.


begin

  {$IFDEF DEBUG}

    ShowMessage('调试模式');

  {$ENDIF}

 

  {$IFDEF RELEASE}

    ShowMessage('发布模式');

  {$ENDIF}

end;



7、编译指令写在哪?:


编译指令可以写在代码页的任何地方, 不过在代码的不同区域有时也会不同;

譬如: {$APPTYPE GUI} {$APPTYPE CONSOLE} 就只能写在工程文件里才有效.

{$APPTYPE GUI}
{$APPTYPE CONSOLE} 分别表示窗口工程和控制台工程.
其中 {$APPTYPE GUI} 是默认的, 所以很少见到它.

它甚至可以嵌入到代码行当中, 譬如 ActnColorMaps 单元就有这么一句:


begin

  SystemParametersInfo(SPI_GETFLATMENU, 0, {$IFNDEF CLR}@{$ENDIF}FlatMenus, 0);

end;



8、条件标识符的有效范围:


Delphi 预定义的条件标识符都是全局的, 我们用 {$DEFINE ...} 自定义的标识符都是局部的.

如何自定义全局的标识符呢?
Project -> Options... ->
选定 Delphi Compiler -> 点击 Conditional defines 右边小按钮 -> 添加.

不过这和系统预定义的还是有区别, 咱们自定义的只能用于当前文件.

如何定义每个文件都可以使用的标识符呢?
Project -> Options... 定义后, 马上选择左下角的 Default.

这和系统预定义的还是有区别, 因为这只能左右以后的文件, 管不着以前存在的文件.
如何...没办法了.

其他编译指令, 譬如在 Debug Release 中的设置也都是这样; 也就是说: 每个文件都有相对独立的编译设置.

看到 Project -> Options... 马上明白了编译指令的设置方法有两种:
1
、使用 {$...} 在代码中嵌入;
2
、从 Project -> Options... 设置.

但在代码中嵌入有时是不可替代的, 譬如现在讨论的条件编译.



9、编译指令有多少?:


现在谈到的还只是条件编译, 实际应用最多的是开关编译; 在任一代码页执行快捷键 Ctrl+O+O , 然后看看最上面...

下面列出了这些默认设置:


{$A8,B-,C+,D+,E-,F-,G+,H+,I+,J-,K-,L+,M-,N-,O+,P+,Q-,R-,S-,T-,U-,V+,W-,X+,Y+,Z1}

{$MINSTACKSIZE $00004000}

{$MAXSTACKSIZE $00100000}

{$IMAGEBASE $00400000}

{$APPTYPE GUI}

{$WARN SYMBOL_DEPRECATED ON}

{$WARN SYMBOL_LIBRARY ON}

{$WARN SYMBOL_PLATFORM ON}

{$WARN SYMBOL_EXPERIMENTAL ON}

{$WARN UNIT_LIBRARY ON}

{$WARN UNIT_PLATFORM ON}

{$WARN UNIT_DEPRECATED ON}

{$WARN UNIT_EXPERIMENTAL ON}

{$WARN HRESULT_COMPAT ON}

{$WARN HIDING_MEMBER ON}

{$WARN HIDDEN_VIRTUAL ON}

{$WARN GARBAGE ON}

{$WARN BOUNDS_ERROR ON}

{$WARN ZERO_NIL_COMPAT ON}

{$WARN STRING_CONST_TRUNCED ON}

{$WARN FOR_LOOP_VAR_VARPAR ON}

{$WARN TYPED_CONST_VARPAR ON}

{$WARN ASG_TO_TYPED_CONST ON}

{$WARN CASE_LABEL_RANGE ON}

{$WARN FOR_VARIABLE ON}

{$WARN CONSTRUCTING_ABSTRACT ON}

{$WARN COMPARISON_FALSE ON}

{$WARN COMPARISON_TRUE ON}

{$WARN COMPARING_SIGNED_UNSIGNED ON}

{$WARN COMBINING_SIGNED_UNSIGNED ON}

{$WARN UNSUPPORTED_CONSTRUCT ON}

{$WARN FILE_OPEN ON}

{$WARN FILE_OPEN_UNITSRC ON}

{$WARN BAD_GLOBAL_SYMBOL ON}

{$WARN DUPLICATE_CTOR_DTOR ON}

{$WARN INVALID_DIRECTIVE ON}

{$WARN PACKAGE_NO_LINK ON}

{$WARN PACKAGED_THREADVAR ON}

{$WARN IMPLICIT_IMPORT ON}

{$WARN HPPEMIT_IGNORED ON}

{$WARN NO_RETVAL ON}

{$WARN USE_BEFORE_DEF ON}

{$WARN FOR_LOOP_VAR_UNDEF ON}

{$WARN UNIT_NAME_MISMATCH ON}

{$WARN NO_CFG_FILE_FOUND ON}

{$WARN IMPLICIT_VARIANTS ON}

{$WARN UNICODE_TO_LOCALE ON}

{$WARN LOCALE_TO_UNICODE ON}

{$WARN IMAGEBASE_MULTIPLE ON}

{$WARN SUSPICIOUS_TYPECAST ON}

{$WARN PRIVATE_PROPACCESSOR ON}

{$WARN UNSAFE_TYPE OFF}

{$WARN UNSAFE_CODE OFF}

{$WARN UNSAFE_CAST OFF}

{$WARN OPTION_TRUNCATED ON}

{$WARN WIDECHAR_REDUCED ON}

{$WARN DUPLICATES_IGNORED ON}

{$WARN UNIT_INIT_SEQ ON}

{$WARN LOCAL_PINVOKE ON}

{$WARN MESSAGE_DIRECTIVE ON}

{$WARN TYPEINFO_IMPLICITLY_ADDED ON}

{$WARN RLINK_WARNING ON}

{$WARN IMPLICIT_STRING_CAST ON}

{$WARN IMPLICIT_STRING_CAST_LOSS ON}

{$WARN EXPLICIT_STRING_CAST OFF}

{$WARN EXPLICIT_STRING_CAST_LOSS OFF}

{$WARN CVT_WCHAR_TO_ACHAR OFF}

{$WARN CVT_NARROWING_STRING_LOST OFF}

{$WARN CVT_ACHAR_TO_WCHAR OFF}

{$WARN CVT_WIDENING_STRING_LOST OFF}

{$WARN XML_WHITESPACE_NOT_ALLOWED ON}

{$WARN XML_UNKNOWN_ENTITY ON}

{$WARN XML_INVALID_NAME_START ON}

{$WARN XML_INVALID_NAME ON}

{$WARN XML_EXPECTED_CHARACTER ON}

{$WARN XML_CREF_NO_RESOLVE ON}

{$WARN XML_NO_PARM ON}

{$WARN XML_NO_MATCHING_PARM ON}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值