C标准预定义宏

作者 YYGCui 日期 2011-07-27
Categories: 技术积累 Tags: Programming C/C++ Macros
C标准预定义宏

C语言标准(ANSI/ISO Standard C)中定义一些了宏命令,称为标准预定义宏(Standard Predefined Macros)。以GCC 4.6.1的文档The C  Preprocess中介绍为例。因为这些宏是在C标准中定义的,所以基本上所有的编译器都支持(特别老的编译器除外),可以肯定的是,C99标准支持所有的这些标准预定义宏。这些宏都是以双下划线__开始的。

__FILE__
这个宏表示当前文件的文件名,其类型是字符串。它表示预处理器打开这个文件的路径,并不是像#include指令包含的short name,或者文件名参数。这个路径是以该程序所在目录为基点的相对路径,比如当前目录下,该宏的值可能是myheader.h;引用标准头文件时,该宏的值可能是/usr/local/include/myheader.h 。

__LINE__
该宏表示当前输入的行的行号,其类型是整型。严格来说,它不算是一个预定义宏,因为它的值是随着源文件的变化而变化的。

__func__
该宏是在C99标准中引入的,它表示当前的正在执行的函数名 ,其类型是字符串。严格来说,它不算是宏,因为预处理器无法知道当前正在执行的函数名。

以上这三个宏对于debug程序是非常有用的,可以轻松定位到哪个源文件、哪个函数、哪一行附近出现了问题。例如一下示例程序的showtrace()函数。除了这三个常用的宏之外,还有一些预定义宏。

__DATE__
该宏表示预处理器开始执行的日期,其类型是字符串。它有十一个字符组成,形如"Jul 27 2011" ,若天数少于10,则在左侧补一空格,如"Jul  7 2011"。

__TIME__
该宏表示预处理器开始执行的时间,其类型是字符串。它有八个字符组成,形如“18:53:09"。

__STDC__
该宏表示使用的编译器是否支持C标准。在GCC中,该宏的值为1,表示使用的编译器支持ISO Standard C。 如果-traditional-cpp选项被使用的话,该宏将不被定义。在非GCC环境下,其具体数值可能不一样,即可能值为0表示支持ISO Standard C。

__STDC_VERSION__
该宏表示使用的编译器所支持的C标准的版本号, 其类型是长整型,格式为yyyymmL,其中yyyy表示年份,mm表示月份。199409L表示1989标准修订于1994,199901L表示1999标准,对1999标准的支持还没有完成。如果-traditional-cpp选项被使用,或者编译C++或者Objective-C时,该宏将不被定义。
:我在使用时,发现c89标准不支持该宏,反而是c99标准支持。

__STDC_HOSTED__
该宏被定义时,其值为1,表示编译环境为宿主环境(hosted envir0nment)。宿主环境下可以使用所有的标准库,程序是借助于操作系统运行的。与之相对的是独立环境(freestanding environment),像操作系统,嵌入式系统或者一些固件就是这种环境,它不使用标准库,不依赖于OS。

__cplusplus
该宏在使用C编译器时被定义,可以用来区分是由C编译器编译的还是有C编译器编译的。GCC还没有完全支持该宏,使用1表示其值而不是标准C++版本号。

__OBJC__
该宏在使用Objective-C编译器时被定义,其值为1 。

__ASSEMBLER__
当预处理汇编语言时该宏被定义,其值为1。

以下示例程序用来查看这些宏定义的值。编译时,请使用c99标准,命令如下:

$gcc -o spMacros spMacros.c -std=c99

特别指出的是,showtrace()函数简单的模拟了出错输出,其形式类似于编译错误输出。

    /* standard predefined Macros */
    
    #include <stdio.h>
    #include <stdlib.h>
    
    void showtrace(char *file, long line, const char *func);
    
    int main()
    {
        printf("The source file name is %s.\n",__FILE__);
        printf("The current line number is %d.\n",__LINE__);
        printf("The compile date is %s.\n",__DATE__);
        printf("The compile time is %s.\n",__TIME__);
        printf("The current function name is %s.\n",__func__);
    #ifdef __STDC__
        printf("The used compiler conforms to ISO Standard C.\n");
        printf("The C Standard's version is %ld.\n",__STDC_VERSION__);
    #endif
    #ifdef __STDC_HOSTED__
        printf("The compiler's target is a hosted environment.\n");
    #endif
        
    #if defined __cplusplus
        printf("the C++ compiler is in use.\n");
    #elif defined __OBJC__
        printf("the Object-C compiler is in use.\n");
    #elif defined __ASSEMBLER__
        printf("assembly language is preprocessing.\n");
    #else
        printf("the C compiler is in use.\n");
    #endif
        
        printf("\n\n");

        showtrace(__FILE__, __LINE__, __func__);
        return 0;
    }

    void showtrace(char *file, long line, const char* func)
    {
        fprintf(stderr,"%s: In function '%s':\n", file, func);
        fprintf(stderr,"%s:%d: simulate the compiler standard error output.\n", file, line);
    }