1. 程式人生 > >C程式中函式名與巨集名稱同名

C程式中函式名與巨集名稱同名



C語言中,函式名稱和巨集名稱可以相同。可以參考下面的示例程式。
///////////////////////////////////////////test.cpp
#include <stdio.h>




void print(int value) {
    printf("%d\n", value);
}




#define print(x)  printf("hello");    \
                print(x)




int main() {
    print(23);




    return 0;
}
上面的程式在vc和gcc下都可以執行,輸出結果是:hello23。
究其原因,我們知道編譯器編譯C語言程式時,先執行預編譯,然後再執行編譯、彙編和連結等步驟。預編譯階段質主要處理巨集,而編譯階段同名的巨集已經被替換掉了,故而此時是不存在識別符號衝突的。
但是,函式名稱和巨集名稱同名是有前提的,同名的巨集定義必須在同名函式實體之下。再請參考下面示例程式。
/////////////////////////test.cpp
#include <stdio.h>


#define print(x)  printf("hello");    \
                print(x)




void print(int value) {
    printf("%d\n", value);
}




int main() {
    print(23);




    return 0;
}
這個程式是編譯不過去的,因為巨集定義在同名函式定義之前,預編譯到print函式時,其名稱也被當做巨集進行處理,預編譯完畢後,編譯器編譯是程式顯然是不對的。如果程式的檔名稱是test.c,則linux環境可以通過命令gcc -E test.c > test.i,可以看到預編譯結果,有心者可以自己分析下,仔細看看print函式的預編譯結果。
如果要定義一個與函式名同名的函式,我們須在函式定義之後再定義巨集,似乎不太優雅,沒有別的方法麼?有的,多檔案實現之。有多檔案及其原始碼如下:
/////////////////////////print.h
#ifndef __PRINT_H__
#define __PRINT_H__




void print(int value);




#endif




/////////////////////////print.cpp
#include "print.h"
#include <stdio.h>




void print(int value) {
printf("%d\n", value);
}




/////////////////////////print_inf.h
#ifndef __PRINT_INF_H__
#define __PRINT_INF_H__




#include "print.h"




//print macro
#defineprint(x)printf("hello");\
print(x) //print function




#endif








/////////////////////////test.cpp
#include "print_inf.h"
#include <stdio.h>

int main() {
print(23);




return 0;
}
編譯程式命令是gcc test.c print.c -o test,執行程式test,輸出是hello23。
okay,問題又一次解決。此時,可能有一個疑問,巨集與函式同名,有什麼用?還是僅僅為了炫耀?
考慮如下場景,如果程式庫print版本更新,我覺得print.h中的print函式功能有限,需要擴充一下,實現一個print_ex函式,而此時我沒有定義一個print巨集,呼叫這個print函式的地方改怎麼辦?
當然可以把呼叫舊版本print函式的程式碼都更新為print_ex函式,當然,你得費力費心。
但是,如果舊版本庫做的比較好,而且考慮周全,已經定義了一個與print函式同名的print巨集呢?我是不是僅僅把print巨集中的print函式更改為print_ex就可以了?是不是很方便?而且,不管新版本的函式名稱如何更改,因為一個巨集的存在,呼叫print庫使用者不必關心新版本更新了那些內容,也無需更改程式碼,僅僅重新編譯程式即可。新的示例程式碼如下:
/////////////////////////print.h
#ifndef __PRINT_H__
#define __PRINT_H__




void print(int value);
void print_ex(int value);




#endif




/////////////////////////print.cpp
#include "print.h"
#include <stdio.h>




void print(int value) {
printf("%d\n", value);
}




void print_ex(int value) {
printf("%d\n", value + 10);
}




/////////////////////////print_inf.h
#ifndef __PRINT_INF_H__
#define __PRINT_INF_H__




#include "print.h"




//print macro
#defineprint(x)printf("hello");\
print_ex(x) //print function




#endif




/////////////////////////test.cpp
#include <stdio.h>
#include "print_inf.h"




int main() {
    print(23);




    return 0;
}
上面編譯程式命令同樣是gcc test.c print.c -o test,執行程式test,輸出是hello33。