c編譯器預定義巨集(轉載)
阿新 • • 發佈:2021-11-29
為了方便處理一些有用的資訊,前處理器定義了一些預處理識別符號,也就是預定義巨集。預定義巨集的名稱都是以“__”(兩條下劃線)開頭和結尾的,如果巨集名是由兩個單片語成,那麼中間以“_”(一條下劃線)進行連線。並且,巨集名稱一般都由大寫字元組成。
在日常專案程式設計中,預定義巨集尤其對多目標平臺程式碼的編寫通常具有重大意義。通過預定義巨集,程式設計師使用“#ifdef”與“#endif”等預處理指令,就可使平臺相關程式碼只在適合於當前平臺的程式碼上編譯,從而在同一套程式碼中完成對多平臺的支援。從這個意義上講,平臺資訊相關的巨集越豐富,程式碼的多平臺支援越準確。
標準 C 語言提供的一些標準預定義巨集如表 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標準及其指定年月的修訂補充,否則該巨集為未定義 |
除標準 C 語言提供的標準巨集之外,各種編譯器也都提供了自己的自定義預定義巨集。可以通過表 2 所示的指令來檢視不同編譯器對預定義巨集的支援情況。
編譯器 | 巨集指令(c) | 巨集指令(C++) |
---|---|---|
Clang/LLVM | clang -dM -E -x c /dev/null | clang++ -dM -E -x C++ /dev/null |
GNUGCC/G++ | gcc -dM -E -x c /dev/null | g++ -dM -E -xC++/dev/null |
Hewlett-Packard C/aC++ | cc -dM -E -x c /clev/null | aCC -dM -E -xC++/dev/null |
IBM XL C/C++ | xlc -qshowmacros -E /dev/null | xlc++ -qshowmacros -E /dev/null |
Intel ICC7ICPC | icc -dM -E -x c /dev/null | icpc -dM -E -xC++/dev/null |
Oracle Solaris Studio | cc -xduinpmacros -E /dev/null | CC -xduinpmacros -E /clev/null |
Portland Group PGCC/PGCPP | pgcc -dM -E |
對於這些預定義巨集的應用,基本上隨處可見,下面舉例介紹。
利用“__DATE__”和“__TIME__”巨集可以用來確定程式編譯的時間。如下面的示例程式碼所示:
int main (void)
{
printf("Copyright (c) Powered by www.develhome.com\n");
printf("Compiled on %s at %s\n", __DATE__,__TIME__);
return 0;
}
利用“__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
利用__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("\n");\
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;
}
最後還需要注意的是,如果使用者重定義“#define“或取消了“#undef”預定義巨集,那麼其結果是“未定義”的。因此,在程式碼編寫中,應該儘量避免自定義巨集與預定義巨集名稱相同的情況發生。