zoukankan      html  css  js  c++  java
  • C/C++预定义宏

    编译器识别预定义的 ANSI/ISO C99 C 预处理宏,Microsoft C++ 实现将提供更多宏。些预处理器宏不带参数,并且不能重新定义。

    ANSI 兼容的预定义宏

    __FILE__,__LINE__,__func__,__DATE__,__TIME__,__TIMESTAMP__
     
    1 . __FILE__,__LINE__,__FUNCTION__或者__func__

    __FILE__:当前程序行所在源文件名称,标准C支持,该宏当做字符串对待;
    __LINE__:当前程序行所在源文件内的行号,标准C支持,该宏当做整形对待;
    __FUNCTION__或者__func__:当前程序行所属的函数名称,C99支持(如:VC++6.0不支持),该宏当做字符串对待;

    结合打印日志功能,这些信息将有助于调试。简单的使用方法:

    //将该程序保存为test.cpp
    #include <iostream>
    using namespace std;
    int main(int argc, char *argv[])
    {
        printf("FILE:%s|LINE:%d|FUNCTION:%s|%s
    ", __FILE__, __LINE__, __FUNCTION__, __func__);
        return 0;
    }

    执行上述程序将打印:FILE:test.cpp|LINE:8|FUNCTION:main|main


    特别说明,据参考资料中关于__func__的信息称,__func__不是一个宏,它是编译隐式声明的常量字符数组:static const char __func__[] = "function-name"。

    2 . __DATE__,__TIME__,__TIMESTAMP__

    __DATE__:当前文件的编译日期,格式是Mmm:dd:yyyy。该宏当做字符串对待。
    __TIME__:当前文件的编译时间,格式是hh:mm:ss。该宏当做字符串对待。

    __TIMESTAMP__:当前源文件的最近一次的修改日期和时间,格式是Ddd Mmm Date hh:mm:ss yyyy 。该宏当做字符串对待。

    编译源文件时,假如该宏,可以让程序打印出编译时间,达到区分不同版本的目的。简单使用方法如下:

    #include <iostream>
    using namespace std;
    int main(int argc, char *argv[])
    {
        printf("DATE:%s|TIME:%s|TIMESTAMP:%s
    ", __DATE__, __TIME__,__TIMESTAMP__);
        getchar();
        return 0;
    }

    执行上述程序将打印:DATE:Oct 20 2010|TIME:23:33:24。

    不重新编译程序的情况下,每次执行该程序打印的都将是是这个时间,而不是系统的当前时间。

    3 -- #line

    #line用于重置由__LINE__和__FILE__宏指定的行号和文件名。比如说我们有这么一个测试程序:

    //将该程序保存为test.cpp
    #include <iostream>
    using namespace std;
    int main(int argc, char *argv[])
    {
    #line 100 "baidu.cpp"
        printf("FILE:%s|LINE:%d
    ", __FILE__, __LINE__);
        return 0;
    }

    注释掉第8行代码,程序打印:FILE:test.cpp|LINE:9
    不注释第8行代码,程序打印:FILE:baidu.cpp|LINE:100

    可见:#line指定下行代码的起始行号和源文件名称,作用域到文件末尾或者再次#line的使用处。

    4 -- __GUNC__

    __GUNC__,是GCC编译器的预定义,表明当前GNUC编译的版本。__GNUC__ 的值表示gcc的版本,需要针对gcc特定版本编写代码时,可以使用该宏进行条件编译。

    6 -- 宏定义的"#"和"##"使用方法

    "#":替换宏参数时,将其后面的宏参数转换成带引号的字符串,例如:

    #define STR(s) #s
    int main()
    {
        std::string str = STR(abcdefg);
        return 0;
    }

    C编译器在预处理代码时,第5行实际翻译成:std::string str = "abcdefg";

    "##":将该符号前后的两个宏参数连接在一起,比如:

    #define PRINT(PRINT_FUNNAME, VAR) print_##PRINT_FUNNAME(VAR)
    int main()
    {
        PRINT(common, 5);
        return 0;
    }

    C编译器在预处理代码时,第5行实际翻译成:print_common(5);

    我们实际看下综合运用的例子:

    //#include <iostream>
    #define PRINT(fun, name, var) print_##fun(#name, var)
    void print_common(const std::string & name, int var)
    {
        std::cout << name << ":" << var << std::endl;
    }
    void print_tofile(const std::string & name, int var)
    {
        char sz_temp[1024];
        memset(sz_temp, 0, sizeof(sz_temp));
        snprintf(sz_temp, sizeof(sz_temp), "%s:%d", name.c_str(), var);
        FILE * fp = fopen("./log.log", "w");
        fwrite(sz_temp, 1, strlen(sz_temp), fp);
        fclose(fp);
    }
    int main()
    {
        PRINT(common, age, 5);
        PRINT(tofile, age, 5);
        return 0;
    }

    这个代码的意思是,在主函数中以统一的调用入口"PRINT"该宏函数,通过制定不同的函数名称,将变量的名称和值打印到不同的地方,比如屏幕或者文件中。
    我们使用g++ -E marco.cpp预处理命令查看下预处理后的源文件:

    # 1 "marco.cpp"
    # 1 "<built-in>"
    # 1 "<command line>"
    # 1 "marco.cpp"
    void print_common(const std::string & name, int var)
    {
        std::cout << name << ":" << var << std::endl;
    }
    void print_tofile(const std::string & name, int var)
    {
        char sz_temp[1024];
        memset(sz_temp, 0, sizeof(sz_temp));
        snprintf(sz_temp, sizeof(sz_temp), "%s:%d", name.c_str(), var);
        FILE * fp = fopen("./log.log", "w");
        fwrite(sz_temp, 1, strlen(sz_temp), fp);
        fclose(fp);
    }
    int main()
    {
        print_common("age", 5);
        print_tofile("age", 5);
        return 0;
    }
     
  • 相关阅读:
    linux下启动和关闭网卡命令及DHCP上网
    python 编码问题
    paddlepaddle
    Convolutional Neural Network Architectures for Matching Natural Language Sentences
    deep learning RNN
    Learning Structured Representation for Text Classification via Reinforcement Learning 学习笔记
    Python IO密集型任务、计算密集型任务,以及多线程、多进程
    EM 算法最好的解释
    tensorflow 调参过程
    tensorflow 学习纪录(持续更新)
  • 原文地址:https://www.cnblogs.com/shijingjing07/p/5508619.html
Copyright © 2011-2022 走看看