2014-12-24 3 views
1

Учитывая следующий исходный код:Может ли _Generic быть функцией? Или можно использовать _Generic с __ атрибутом __ ((очистка))?

#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.