• 预定义宏,C语言预定义的宏详解


    1、预定义宏

    • 对于预定义宏,相信大家并不陌生。为了方便处理一些有用的信息,预处理器定义了一些预处理标识符,也就是预定义宏。预定义宏的名称都是以“__”(两条下划线)开头和结尾的,如果宏名是由两个单词组成,那么中间以“_”(一条下划线)进行连接。并且,宏名称一般都由大写字符组成。
    • 在日常项目编程中,预定义宏尤其对多目标平台代码的编写通常具有重大意义。
    • 通过预定义宏,程序员使用“#ifdef”与“#endif”等预处理指令,就可使平台相关代码只在适合于当前平台的代码上编译,从而在同一套代码中完成对多平台的支持。从这个意义上讲,平台信息相关的宏越丰富,代码的多平台支持越准确。

    2、C标准预定义宏

    • 标准 C 语言提供的一些标准预定义宏如表 1 所示。
    表 1 常用的标准预定义宏
    描 述
    _DATE_ 丐前源文件的编泽口期,用 “Mmm dd yyy”形式的字符串常量表示
    _FILE_ 当前源文件的名称,用字符串常量表示
    _LINE_ 当前源义件中的行号,用十进制整数常量表示,它可以随#line指令改变
    _TIME_ 当前源文件的最新编译吋间,用“hh:mm:ss”形式的宁符串常量表示
    STDC 如果今前编泽器符合ISO标准,那么该宏的值为1,否则未定义
    _STDC_VERSION_ 如果当前编译器符合C89,那么它被定义为199409L;如果符合C99,那么它被定义为199901L:在其他情况下,该宏为宋定义
    _STDC_HOSTED_ (C99)如果当前是宿主系统,则该宏的值为1;如果当前是独立系统,则该宏的值为0
    _STDC_IEC_559 (C99)如果浮点数的实现符合IEC 60559标准时,则该宏的值为1,否则为未定义
    _STDC_IEC_559_COMPLEX_ (C99)如果复数运算实现符合IEC60559标准时,则该宏的伉为1,否则为未定义
    STDC_ISO_10646 (C99 )定义为长整型常量,yyyymmL表示wchai_t值遵循ISO 10646标准及其指定年月的修订补充,否则该宏为未定义

    3、预定义宏的使用

    • 3.1 确定程序编译的时间

      • 利用“_DATE_”和“_TIME_”宏可以用来确定程序编译的时间。如下面的示例代码所示:
      int main (void)
      {
          printf("Copyright (c) Powered by www.develhome.com
      ");
          printf("Compiled on %s at %s
      ", __DATE__,__TIME__);
          return 0;
      }
      
    • 3.2 兼容编译器的程序

      • 利用“_STDC_”与“_STDC_VERSION_”宏可以编写那些需要兼容标准 C 和非标准 C 编译器的程序,如下面的示例代码所示:
      #ifdef __STDC__
      /* Some version of standard C */
      #if defined(__STDC__VERSION__)&&__STDC_VERSION__>=199901L
      /* C99 */
      #elif defined(__STDC_VERSION__)&&__STDC_VERSION__>=199409L
      /* C89 and amendment 1 */
      #else
      /* C89 but not amendment 1*/
      #endif
      #else /* __STDC__not defined */
      /*Not Standard C*/
      #endif
      
    • 3.3 异常跟踪

      • 利用_FILE_、LINE__与_FUNCTION(或者__func_)预定义宏的组合,在调试程序的时候可以很简单地在程序运行期进行异常跟踪。如下面的示例代码所示:
      #include <stdio.h>
      #include <sys/types.h>
      #include <sys/stat.h>
      #include <fcntl.h>
      #include <unistd.h>
      #include <stdlib.h>
      #define MESSAGE(message,assertion) 
                do{
                     if(!(assertion)){
                          printf("line %d in %s(%s)", __LINE__, __FILE__,__FUNCTION__);
                             if(message){
                                  printf(":%s",message);
                                }
                                printf("
      ");
                                abort();
                       }
                   }while(0)
      int OpenFile(const char *filename)
      {
          int fd;
          MESSAGE("文件名称不能够为空",filename);
          MESSAGE("文件不存在",0==access(filename,F_OK));
          fd = open(filename,O_RDONLY);
          close(fd);
          return 0;
      }
      int main(int argc,char **argv)
      {
          MESSAGE("命令参数不能够为空",argc==2);
          OpenFile(argv[1]);
          return 0;
      }
      
      • 其中,_FILE_、LINE__与_FUNCTION(或者_func)预定义宏分别表示文件名、行数与函数名,这样就可以帮助我们精确地定位出现异常的文件、行数与函数名。运行结果如图 4 所示。
      ![](https://img2018.cnblogs.com/blog/1213778/201812/1213778-20181220213218820-859526665.jpg)
      图 4
      - 其中,\__FILE__、__LINE__与\__FUNCTION__(或者\__func__)预定义宏分别表示文件名、行数与函数名,这样就可以帮助我们精确地定位出现异常的文件、行数与函数名。运行结果如图 4 所示。
  • 相关阅读:
    css计数器
    使用area标签模仿a标签
    移动端判断触摸的方向
    简单圆形碰撞检测
    冒泡排序和二分查找算法
    基本数据类型float和double的区别
    HTML5-form表单
    代码块以及它们的执行顺序
    反射
    Excel表格的导入导出
  • 原文地址:https://www.cnblogs.com/CH520/p/10152328.html
Copyright © 2020-2023  润新知