2014-12-24 69 views
1

考慮下面的源代碼:Can _Generic是一個函數嗎?或者_Generic可以與__attribute __((cleanup))一起使用?

#include <stddef.h> 
#include <sys/types.h> 
#include <dirent.h> 

static inline void closedirp(DIR **p) { 
    if (*p) 
     closedir(*p); 
} 

#define auto_cleanup(resource) _Generic((resource),  \ 
    DIR **: closedirp,     \ 
     )(resource) 

int main() { 
#ifdef GENERIC 
    __attribute__((cleanup(auto_cleanup))) DIR * t2 = NULL; 
    t2 = opendir("/tmp"); 
#else 
    __attribute__((cleanup(closedirp))) DIR * t1 = NULL; 
    t1 = opendir("/tmp"); 
#endif 
} 

它編譯和無泄漏運行,沒有限定。然而,當一個定義GENERIC,編譯失敗:

$ gcc foo.c -DGENERIC 
foo.c: In function ‘main’: 
foo.c:16:2: error: cleanup argument not a function 
    __attribute__((cleanup(auto_cleanup))) DIR * t2 = NULL; 
^

這是很沒有意義的使用_Generic的,但是我想擴展它,並處理多種類型資源的自動清理。

回答

1

_Generic不是函數,而是啓動主表達式的關鍵字。

但是在這裏,你似乎更錯誤的軌道上:auto_cleanup是一個宏。像宏這樣的函數具有特殊性,如果沒有()之後它們不會被擴展。因此,在這裏您只需保留標識auto_cleanup以便編譯的後續階段。但是這個標識符沒有被聲明爲這些後期階段的任何東西。

總結:

  • 宏,如果使用得當,會以文本的編制非常早期的階段更換
  • 那麼後期階段會看到一個_Generic表達,並決定哪些是_Generic表達的分支取
  • 只有一個分支,將「生存」,並在代碼的那部分

在所有的編譯這沒有涉及的功能或函數指針,可用於gcc的cleanup擴展。

相關問題