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



    一个程序从无到有的过程是这样的: 编辑代码 -> 预处理 -> 编译(成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}
    
  • 相关阅读:
    ping 原理与ICMP协议
    ARP详解
    TCP,UDP,IP数据包的大小限制
    Java7--try
    递归,尾递归,回溯
    OLEDB数据源
    hexo next主题为博客添加分享功能
    Windows数据库编程接口简介
    2017总结与2018规划
    为 MariaDB 配置远程访问权限
  • 原文地址:https://www.cnblogs.com/del/p/1356774.html
Copyright © 2020-2023  润新知