zoukankan      html  css  js  c++  java
  • 预定义宏,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 所示。
  • 相关阅读:
    父子进程 signal 出现 Interrupted system call 问题
    一个测试文章
    《淘宝客户端 for Android》项目实战 html webkit android css3
    Django 中的 ForeignKey ContentType GenericForeignKey 对应的数据库结构
    coreseek 出现段错误和Unigram dictionary load Error 新情况(Gentoo)
    一个 PAM dbus 例子
    漫画统计学 T分数
    解决 paramiko 安装问题 Unable to find vcvarsall.bat
    20141202
    js
  • 原文地址:https://www.cnblogs.com/CH520/p/10152328.html
Copyright © 2011-2022 走看看